1

監査ログ (誰が、いつ、どのメンバーを変更したか) のために、データ構造の「詳細な比較」を行っています。これにはリフレクションを使用し、構造に再帰してそれらを比較しています。辞書を含むもので問題が発生しました。

によってメンバーが辞書であることを検出できますtypeof(IDictionary).IsAssignableFrom(memberType)。私の計画は、両方のオブジェクトに存在するキーを収集し、それらの再帰を続行することです。ただし、LINQ によって拡張されていない ですIDictionary.KeysICollectionキーのタイプがわからないのですが、どうすればこれを達成できますか?

この方法は最適ではないかもしれません (私は Generics/Reflection コンボの経験がありません)、別の方法でこれを行う必要がありますか?

4

2 に答える 2

1

これは、リフレクションの反復に役立ちます。

IDictionary<int, string> t;

bool t.GetType().IsGenericType
Type[] t.GetType().GetGenericArguments() 
// you can do foreach here and see again if type is generic

最初に型がジェネリックかどうかをテストし、次にジェネリック引数の型を確認するヘルパー メソッドを作成できます。これは、ジェネリック辞書だけでなく、ジェネリック引数を持つすべての型をテストします。IList、KeyValuePair など。

public static bool IsType(Type inputType, Type targetType)
{
    if (inputType.IsGenericType)
    {
        Type[] genericArgs = inputType.GetGenericArguments();
        var foundType = false;
        foreach (var item in genericArgs)
        {
            if (IsType(item, targetType))
                foundType = true;
        }
        return foundType;
    }
    return inputType.IsAssignableFrom(targetType);
}
于 2012-01-18T14:44:00.683 に答える
0

自分で解決策を見つけました。これChangedPropertiesは、プロパティ名を含む型と、変更前後の値です。

if (typeof(IDictionary).IsAssignableFrom(propertyType))
{
    Type keyType = propertyType.GetGenericArguments()[0],
         valueType = propertyType.GetGenericArguments()[1];
    Type hashsetType = typeof(HashSet<>).MakeGenericType(keyType);
    var hashsetCtor = hashsetType.GetConstructor(new[] { typeof(IEnumerable<>).MakeGenericType(keyType) });

    dynamic aDict = a;
    dynamic bDict = b;
    dynamic aKeys = hashsetCtor.Invoke(new object[] { aDict.Keys });
    dynamic bKeys = hashsetCtor.Invoke(new object[] { bDict.Keys });

    List<ChangedProperty> changes = new List<ChangedProperty>();
    foreach (var key in Enumerable.Intersect(aKeys, bKeys))
    {
            // Present in both dictionaries. Recurse further
    }
    foreach (var key in Enumerable.Except(aKeys, bKeys))
    {
          // Key was removed
    }
    foreach (var key in Enumerable.Except(bKeys, aKeys))
    {
          // Key was added
    }

    return changes;
}
于 2012-01-19T13:14:06.503 に答える