fix(opcua): structural equality for EquipmentVirtualTagPlan so no-op redeploys diff empty
IReadOnlyList<string> DependencyRefs compared by reference in the auto-generated record equality, causing every VirtualTag with dependencies to be flagged "Changed" on every parse (fresh list instances from composer and artifact-decoder). Add Equals/GetHashCode overrides with element-wise ordinal comparison so Phase7Plan.IsEmpty short-circuits a no-op redeploy. Add regression test Identical_virtualtag_snapshots_diff_to_empty_plan (separate list instances, same contents → IsEmpty true). Add TODO comment in Phase7Applier near needsRebuild predicate.
This commit is contained in:
@@ -122,7 +122,31 @@ public sealed record EquipmentVirtualTagPlan(
|
||||
string Name,
|
||||
string DataType,
|
||||
string Expression,
|
||||
IReadOnlyList<string> DependencyRefs);
|
||||
IReadOnlyList<string> DependencyRefs)
|
||||
{
|
||||
/// <summary>Structural equality: the auto-generated record equality would compare
|
||||
/// <see cref="DependencyRefs"/> (an interface-typed list) BY REFERENCE, flagging every
|
||||
/// VirtualTag as "changed" on every parse (fresh list instances). Compare it element-wise
|
||||
/// so a no-op redeploy diffs empty.</summary>
|
||||
public bool Equals(EquipmentVirtualTagPlan? other) =>
|
||||
other is not null &&
|
||||
VirtualTagId == other.VirtualTagId &&
|
||||
EquipmentId == other.EquipmentId &&
|
||||
FolderPath == other.FolderPath &&
|
||||
Name == other.Name &&
|
||||
DataType == other.DataType &&
|
||||
Expression == other.Expression &&
|
||||
DependencyRefs.SequenceEqual(other.DependencyRefs, StringComparer.Ordinal);
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hash = new HashCode();
|
||||
hash.Add(VirtualTagId); hash.Add(EquipmentId); hash.Add(FolderPath);
|
||||
hash.Add(Name); hash.Add(DataType); hash.Add(Expression);
|
||||
foreach (var r in DependencyRefs) hash.Add(r, StringComparer.Ordinal);
|
||||
return hash.ToHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pure composer that flattens the live-edit DB tables into the address-space build plan a
|
||||
|
||||
Reference in New Issue
Block a user