Skip to content

[Feature]: uml4net.Extensions -> generate IComparers for each Concrete interface #60

@samatstariongroup

Description

@samatstariongroup

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of the SysML2.NET
  • I have searched open and closed issues to ensure it has not already been reported

Description

code generate:

  • IEqualityComparer for each concrete UML class:
    - ignore derived and redefined properties
    - anchor equality on the stable identity first (e.g., Id/Iid), then compare properties.
    - Add Diff function to comparer (see snippet below)
  • Generate a static polymorphic root comparer (for mixed lists)

Sample code - (refine if necessary -> optimize for runtime performance)

public static IEnumerable<string> Diff(IElement a, IElement b)
{
    if (a.Id != b.Id) yield return $"Id: {a.Id} != {b.Id}";
    if (a.Name != b.Name) yield return $"Name: '{a.Name}' != '{b.Name}'";
    // ...
}

Sample code - (refine if necessary -> optimize for runtime performance)

public sealed class Comparer : IEqualityComparer<IData>
{
    private readonly IReadOnlyDictionary<Type, IEqualityComparer<IData>> interfaceComparers;

    public Comparer(IReadOnlyDictionary<Type, IEqualityComparer<IData>> interfaceComparers)
        => this.interfaceComparers = interfaceComparers;

    public bool Equals(IData? x, IData? y)
    {
        if (ReferenceEquals(x, y)) return true;
        if (x is null || y is null) return false;

        var ix = PickInterface(x);
        var iy = PickInterface(y);

        if (ix != iy) return false;

        if (!interfaceComparers.TryGetValue(ix, out var c))
            throw new NotSupportedException($"No comparer registered for interface {ix.FullName}");

        return c.Equals(x, y);
    }

    public int GetHashCode(IData obj)
    {
        var i = PickInterface(obj);
        var id = TryGetId(obj);
        return HashCode.Combine(i, id);
    }

    private static Type PickInterface(IData obj)
    {
        var t = obj.GetType();
        foreach (var i in InterfacePriority)
        {
            if (i.IsAssignableFrom(t))
                return i;
        }

        throw new NotSupportedException($"Unable to map runtime type {t.FullName} to a known DTO interface.");
    }

    private static object? TryGetId(IData obj)
        => obj switch
        {
            IHasId h => h.Id,
            _ => null
        };
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions