У меня есть этот метод под названием MatchNodes: IEnumerable<bool> MatchNodes<T>(T n1, T n2)
Который в основном получает каждое свойство и поле от обоих T
объектов (через отражение, не включая свойства / поля из базовых классов) и сравнивает их, возвращая результат в виде IEnumerable из bools.
Когда он находит примитивный тип или строку, он просто возвращает ==
между ними.
Когда он находит тип, производный от коллекции, он выполняет итерацию каждого члена и вызывает MatchNodes
для каждого из них (ой).
Когда он находит любой другой тип, он вызывает MatchNodes
для каждого свойства / поля.
Мое решение, очевидно, запрашивает исключение переполнения стека, но я понятия не имею, как сделать его лучше, потому что я понятия не имею, как глубоко зайдут объекты.
Код (постарайтесь не плакать, пожалуйста, это ужасно ужасно) :
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;
}
}
То, на что я смотрю, - это способ ползти в объекты без рекурсивного вызова моего метода.
EDIT
Для пояснения, пример:
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)
, где n1.GetType()
и n2.GetType()
равны Class2
, вернет true, если:
- Каждый
Class1
объект внутри MyClassProp1
имеет одинаковые Str1
, Int1
для обоих объектов
MyClassProp2
имеет одинаковые Str1
, Int1
для обоих объектов
MyStr
равно для обоих объектов
И я не буду сравнивать какие-либо свойства с RandomClassWithMoreProperties
.