I have a generic object comparison method which I use to compare two models with the same structure.
public static List<Variance> DetailedCompare<T>(this T val1, T val2)
{
var variances = new List<Variance>();
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in properties.Where(t => t.IsMarkedWith<IncludeInComparisonAttribute>()))
{
var v = new Variance
{
PropertyName = property.Name,
ValA = property.GetValue(val1, null),
ValB = property.GetValue(val2, null)
};
if (v.ValA == null && v.ValB == null) { continue; }
if (v.ValA != null && !v.ValA.Equals(v.ValB))
{
variances.Add(v);
}
}
return variances;
}
The problem I have is that sometimes an object is passed to it that may contain a list of other objects within it. Because it only compares at the top level it just returns that the object array was changed. Ideally I would like it to go through the nested array and look at the changed values as well.
Ideally I think it should probably make a recursive call when it finds an object array. Any ideas how I might go about this?
Edit - with working examples
Here are some .net fiddle examples of how this is meant to work.
This is the first code example that doesn't search down through the nested objects and just reports that the collection has changed (as per the code above):
https://dotnetfiddle.net/Cng7GI
returns:
Property: NumberOfDesks has changed from '5' to '4'
Property: Students has changed from 'System.Collections.Generic.List1[Student]' to 'System.Collections.Generic.List1[Student]'
Now if I try and call the DetailedCompare if I find a nested array using:
if (v.ValA is ICollection)
{
Console.WriteLine("I found a nested list");
variances.AddRange(v.ValA.DetailedCompare(v.ValB));
}
else if(v.ValA != null && !v.ValA.Equals(v.ValB)){
variances.Add(v);
}
it doesn't look like the recursive call works
https://dotnetfiddle.net/Ns1tx5
as I just get:
I found a nested list Property: NumberOfDesks has changed from '5' to '4'
If I add:
var list = v.ValA.DetailedCompare<T>(v.ValB);
inside the Collection check, I get an error that:
object does not contain a definition for 'DetailedCompare' ... Cannot convert instance argument type 'object' to T
really what I want from it is just a single array of all the property names and their value changes.
Property: NumberOfDesks has changed from '5' to '4'
Property: Id has changed from '1' to '4'
Property: FirstName has changed from 'Cheshire' to 'Door'
etc

dictionary["level1"] or dictionary["level2"]etc... Would you appreciate that?if (ValA is IEnumerable eA && ValB is IEnumerable eB)and do some custom logic where you iterate through and callDetailCompare. Then you just need to make an overload forDetailComparethat takes aTypeinstead of<T>