私は、このメソッドと呼ばMatchNodes有する:基底クラスからのプロパティ/フィールドを含まない基本的反射を介して(両方T
オブジェクトからすべてのプロパティフィールドを取得IEnumerable<bool> MatchNodes<T>(T n1, T n2)
防止スタックオーバーフロー
、および)、それらを比較し、その結果をIEnumerableのboolとして返します。
プリミティブ型または文字列を検出した場合、それらの間に==
が返されます。
コレクションから派生した型を検出すると、各メンバーを繰り返し処理し、それぞれのメンバーに対してMatchNodes
を呼び出します(ud)。
他の型が見つかると、プロパティ/フィールドごとに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
、例:MyClassProp1
内部のすべてのClass1
オブジェクトが同じを持って
- :
n1.GetType()
とn2.GetType()
があればClass2
はtrueを返しますされている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)
0、両方のオブジェクトのInt1
MyClassProp2
両方のオブジェクトのInt1
MyStr
が両方のオブジェクト
用等しく、IはRandomClassWithMoreProperties
から任意の特性を比較しないであろう、同じStr1
を有しています。
メソッドを自分で書き直すことなく、再帰的に記述できるメソッドもループとして書き込むことができます。難しいことは自明ではないかもしれませんが、それは既知のCSの基礎であり、自分自身を採用しています。 – user978122
ループとしても、オブジェクトグラフのサイクルを監視する必要があります。また、あなたの再帰呼び出しは、 'T'ジェネリックパラメータとして' object'を使います。これは 'DeclaringType == typeof(T)'をチェックしているので、おそらくあなたが望むものではありません。あなたは正確に何をしようとしていますか?おそらくもっと良い方法があります。 –
また、2つの文字列を与えるとどうなりますか? 'typeof(String).GetProperties()'のforeachプロパティは、 'str1 == str2'である' func'を呼び出します。これはおそらくあなたがすることではありません。 –