I have this method called MatchNodes: IEnumerable<bool> MatchNodes<T>(T n1, T n2)
Which basically gets every property and field from both T objects (via reflection, and not including properties/fields from base classes) and compares them, returning the result as a IEnumerable of bools.
When it finds a primitive type or string, if just returns the == between them.
When it finds a type derived from a collection, it iterates each member and calls MatchNodes for each of them (ouch).
When it finds any other type, it calls MatchNodes for each property/field.
My solution is obviously asking for a stack overflow exception, but I don't have a clue on how make it better, because I have no idea how deep the objects will go.
Code (try not to cry please, it's ugly as hell):
public static IEnumerable<bool> MatchNodes<T>(T n1, T n2)
{
Func<PropertyInfo, bool> func= null;
if (typeof(T) == typeof(String))
{
String str1 = n1 as String;
String str2 = n2 as String;
func = new Func<PropertyInfo, bool>((property) => str1 == str2);
}
else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(typeof(T)))
{
System.Collections.IEnumerable e1 = (System.Collections.IEnumerable)n1;
System.Collections.IEnumerable e2 = (System.Collections.IEnumerable)n2;
func = new Func<PropertyInfo, bool>((property) =>
{
foreach (var v1 in e1)
{
if (e2.GetEnumerator().MoveNext())
{
var v2 = e2.GetEnumerator().Current;
if (((IEnumerable<bool>)MatchNodes(v1, v2)).All(b => b == true))
{
return false;
}
}
else
{
return false;
}
}
if (e2.GetEnumerator().MoveNext())
{
return false;
}
else return true;
});
}
else if (typeof(T).IsPrimitive || typeof(T) == typeof(Decimal))
{
func = new Func<PropertyInfo, bool>((property) => property.GetValue(n1, null) == property.GetValue(n2, null));
}
else
{
func = new Func<PropertyInfo, bool>((property) =>
((IEnumerable<bool>)MatchNodes(property.GetValue(n1, null),
property.GetValue(n2, null))).All(b => b == true));
}
foreach (PropertyInfo property in typeof(T).GetProperties().Where((property) => property.DeclaringType == typeof(T)))
{
bool result =func(property);
yield return result;
}
}
What I'm looking at is a way to crawl into the objects without calling my method recursively.
EDIT
To clarify, example:
public class Class1 : RandomClassWithMoreProperties{
public string Str1{get;set;}
public int Int1{get;set;}
}
public class Class2{
public List<Class1> MyClassProp1 {get;set;}
public Class1 MyClassProp2 {get;set;}
public string MyStr {get;set;}
}
MatchNodes(n1,n2) where n1.GetType() and n2.GetType() are Class2 would return true if:
- Every
Class1object insideMyClassProp1has the sameStr1,Int1for both objects MyClassProp2has the sameStr1,Int1for both objectsMyStris equal for both objects
And I won't compare any properties from RandomClassWithMoreProperties.
objectas theTgeneric parameter - this is probably not what you want since you check thatDeclaringType == typeof(T). What exactly are you trying to do? There is probably a better way.foreach property in typeof(String).GetProperties()it's going to callfunc, which isstr1 == str2. This is probably not what you meant to do.Tends up being always of type object, unless I cast the objects todynamicbefore calling MatchNodes. I have no clue of what problem casting todynamiccould cause, though.