我有這種方法稱爲MatchNodes:IEnumerable<bool> MatchNodes<T>(T n1, T n2)
而通過反射在c#爬行內部的對象防止堆棧溢出
這基本上會從兩個T
對象的每個屬性和字段(通過反射,並且不包括從基類屬性/字段)並比較它們,將結果作爲IEnumerable的bools返回。
當它找到一個原始類型或字符串時,如果只是在它們之間返回==
。
當它找到從集合派生的類型時,它會迭代每個成員併爲其中的每個成員調用MatchNodes
(ouch)。
當它找到任何其他類型時,它會爲每個屬性/字段調用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;
}
}
我正在尋找的是爬進對象,而不調用我的方法遞歸的方式。
編輯
爲了澄清,例如:
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,如果:
- 內
MyClassProp1
每個Class1
對象具有相同的Str1
,Int1
兩個對象 MyClassProp2
具有相同的Str1
,Int1
兩個對象MyStr
等於兩個對象
而且我不會從RandomClassWithMoreProperties
任何性質比較。
不用自己重寫方法,任何可以寫成遞歸的方法也可以寫成循環。其中的困難可能不是微不足道的,但它是一個已知的CS基礎知識,也是我自己僱用的一個。 – user978122 2011-12-22 18:17:57
即使是循環,您仍需要注意對象圖中的週期。另外,遞歸調用使用'object'作爲'T'泛型參數 - 這可能不是您想要的,因爲您檢查了'DeclaringType == typeof(T)'。你究竟想要做什麼?可能有更好的方法。 – 2011-12-22 18:28:36
另外,看看如果你給它兩個字符串會發生什麼:'typeof(String).GetProperties()'中的foreach屬性'它將調用'func',它是'str1 == str2'。這可能不是你想要做的。 – 2011-12-22 18:33:08