-1

How to compare and get differences between two classes.

public class Class1{

public string S1{get;set;}
public string S2{get;set;}
public Class2 C3{get;set;}
}

public class Class2{

public string S1{get;set;}
public string S2{get;set;} 
}

public class Class3{

public string S1{get;set;}
public string S2{get;set;}
public string S12{get;set;}
public Class4 C3{get;set;}
}

public class Class4{

public string S1{get;set;}
public string S2{get;set;}
public string S112{get;set;} 
}

At the end I want to know that there is missing member witout creating instances of classes

public string S112{get;set;}   

and

public string S12{get;set;}

2 Answers2

1

Let's suppose you have these two classes:

public class ClassA
{
    public int Id { get; set; }
    public string Description { get; set; }
    public DateTime CreatedAt { get; set; }
}

public class ClassB
{
    public string Id { get; set; }
    public string Description { get; set; }
    public string CreatedBy { get; set; }
}

To retrieve only those properties that are defined in that class (and not inherited):

public static Dictionary<string, PropertyInfo> GetProperties<TClass>() where TClass : class
{
    return typeof(TClass)
        .GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
        .ToDictionary(prop => prop.Name);
}

To spot the missing ones:

public static IEnumerable<string> GetMissingProperties(string lhsName, IList<string> lhsPropertyNames, string rhsName, IList<string> rhsPropertyNames)
{
    var lhsMissingOnes = lhsPropertyNames.Except(rhsPropertyNames).Select(prop => lhsName + " defines " + prop + " but " + rhsName + " does not.");
    var rhsMissingOnes = rhsPropertyNames.Except(lhsPropertyNames).Select(prop => rhsName + " defines " + prop + " but " + lhsName + " does not.");
    return lhsMissingOnes.Union(rhsMissingOnes);
}

To spot the ones with different types:

public static IEnumerable<string> GetDifferentlyTypedProperties(string lhsName, Dictionary<string, PropertyInfo> lhsProperties, string rhsName, Dictionary<string, PropertyInfo> rhsProperties)
{
    var differentTypes = new List<string>();
    var definedInBoth = lhsProperties.Keys.Intersect(rhsProperties.Keys);
    foreach (var prop in definedInBoth)
    {
        var lhsType = lhsProperties[prop].PropertyType;
        var rhsType = rhsProperties[prop].PropertyType;

        if (lhsType != rhsType)
        {
            var message = prop + " has a type '" + lhsType + "' in " + lhsName + " and '" + rhsType + "' type in " + rhsName;
            differentTypes.Add(message);
        }
    }
    return differentTypes;
}

Putting everything all together:

public static void Main()
{
    var propertiesOfA = GetProperties<ClassA>();
    var propertiesOfB = GetProperties<ClassB>();

    var missingProperties = GetMissingProperties(nameof(ClassA), propertiesOfA.Keys.ToList(), nameof(ClassB), propertiesOfB.Keys.ToList());
    foreach (var message in missingProperties) Console.WriteLine(message);

    var differentProperties = GetDifferentlyTypedProperties(nameof(ClassA), propertiesOfA, nameof(ClassB), propertiesOfB);
    foreach (var message in differentProperties) Console.WriteLine(message);
}

The output will be:
ClassA defines CreatedAt but ClassB does not.
ClassB defines CreatedBy but ClassA does not.
Id has a type 'System.Int32' in ClassA and 'System.String' type in ClassB

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
0

You can get a list of properties / types of each class

var propNameType1 = typeof(Class1).GetProperties()
                        .Select(prop => new  {
                          name = prop.Name,
                          type = prop.PropertyType.Name
                        } )
                        .ToList();

 var propNameType2 = typeof(Class2).GetProperties()
                       .Select(prop => new {
                           name = prop.Name,
                           type = prop.PropertyType.Name
                       })
                       .ToList();

And then you can compare the lists with LINQ

var differences = propNameType1.Except(propNameType2).ToList();