1

我正在对审计日志的数据结构进行“深度比较”(谁更改了哪些成员,何时更改)。我为此使用反射,递归到结构中并比较它们。虽然我遇到了包含字典的问题。

我可以检测到一个成员是字典typeof(IDictionary).IsAssignableFrom(memberType)。然后我的计划是收集两个对象中都存在的键,并继续对它们进行递归。但是,IDictionary.KeysICollectionLINQ 没有扩展的。不知道键的类型,我怎么能做到这一点?

也许这种方法不是最理想的(我在泛型/反射组合方面没有那么经验),我应该用另一种方式来做吗?

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 回答