3

プロパティを比較したい複雑なオブジェクトがいくつかあります。次のコードは、コレクションに到達するまではうまく機能します。コレクションの各メンバーで関数を再帰的に呼び出したいと思います。HasPropertyChanged を再度呼び出すことができるように、誰かがコレクション内のオブジェクトのタイプを判断するのを手伝ってくれませんか?

この疑似コードは私の意図を示しています

      if (p.GetType() == typeof(System.Collections.Generic.List<>))
       {
            foreach (var blah in //the list)
            {
                HasPropertyChanged<//TheType>(Type obj1, Type obj2, null);
            }
        }

また、コードのこの部分は私を悩ませます。tostring メソッドを呼び出さないと、id 63633 が 63633 と等しくないなど、奇妙な結果が得られます。

    object val1 = Original.GetType().GetProperty(p.Name).GetValue(Original, null);
        object val2 = Modified.GetType().GetProperty(p.Name).GetValue(Modified, null);
        if (!IgnoreProperties.Contains(p.Name) && 
            val1 != null && val2 != null && 
            val1.ToString() != val2.ToString())
        {
            return true;
        }

こちらがその全貌です。

private bool HasPropertyChanged<T>(T Original, T Modified, string[] IgnoreProperties)
    {
        if (Original == null || Modified == null)
            return false;
        if (IgnoreProperties == null)
            IgnoreProperties = new string[] { };

        IEnumerable<PropertyInfo> properties = typeof(T).GetProperties();

        foreach (var p in properties)
        {
            if (p.GetType() == typeof(System.Collections.Generic.List<>))
            {
                foreach (var blah in //the list)
                {
                    HasPropertyChanged<//TheType>(Type obj1, Type obj2, null);
                }
            }
            object val1 = Original.GetType().GetProperty(p.Name).GetValue(Original, null);
            object val2 = Modified.GetType().GetProperty(p.Name).GetValue(Modified, null);
            if (!IgnoreProperties.Contains(p.Name) && 
                val1 != null && val2 != null && 
                val1.ToString() != val2.ToString())
            {
                return true;
            }
        }
        return false;
    }
4

2 に答える 2

1

実行時に型を扱っているため、Typeパラメーターを取る関数の非ジェネリック バージョンが必要です。

private bool HasPropertyChanged<T>(T Original, T Modified, string[] IgnoreProperties)
{
    return HasPropertyChanged(typeof(T), Original, Modified, IgnoreProperties);
}

private bool HasPropertyChanged(Type T, object Original, object Modified, string[] IgnoreProperties)
{
    // ...
}

これで、リスト要素のメソッドを呼び出すことができます:

if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>))
{
    object val1 = p.GetValue(Original, null);
    object val2 = p.GetValue(Modified, null);

    // First check count...
    PropertyInfo countProperty = p.PropertyType.GetProperty("Count");
    int count1 = countProperty.GetValue(val1, null);
    int count2 = countProperty.GetValue(val2, null);
    if (count1 != count2) return true;

    // Now iterate:
    var enumerator1 = (val1 as System.Collections.IEnumerable).GetEnumerator();
    var enumerator2 = (val2 as System.Collections.IEnumerable).GetEnumerator();
    while (enumerator1.MoveNext())
    {
        enumerator2.MoveNext();
        // check for null, skipping here...
        object elem1 = enumerator1.Current;
        object elem2 = enumerator2.Current;
        if (HasPropertyChanged(elem1.GetType(), elem1, elem2, IgnoreProperties)) return true;
    }
}
// ...
于 2012-05-17T21:49:18.157 に答える
1

まず、Equals() ではなく == の使用に注意する必要があります。すべてのプロパティ値をオブジェクトとして抽出しています。

object val1 = Original.GetType().GetProperty(p.Name).GetValue(Original, null);
object val2 = Modified.GetType().GetProperty(p.Name).GetValue(Modified, null);

そして、等値演算子を使用してそれらを比較します。参照型の場合、この演算子は、同じインスタンスである場合にのみ true を返します。この場合、同じインスタンスになることはありません。val1 と val2 は 2 つの異なるオブジェクトであるためです。.ToString() 呼び出しを削除して、; に置き換えることができます。

if (val1.Equals(val2) { ... }

これは、あなたがやろうとしていることに対するより正しいアプローチです (私は思います)。

コレクションの問題については、試してみませんか。

if (p is IEnumerable)
{
    foreach (object o in p)
    {
        if (!o.HasPropertyChanged(...))
            return false;
    }
}

これをジェネリックで実装する必要はないと思います。私が見ることができるジェネリック型の唯一の目的は、渡される型が同じであることを確認することです。したがって、それを削除して、T を「Type」または「Object」に変更し、関数の最初の行で型の比較を行います。

if (Original.GetType() != Modified.GetType())
    return false;
于 2012-05-17T21:55:38.350 に答える