确定类型是否可以转换为 IDictionary,其中 Key 可以是任何类型

本文关键字:类型 object 其中 Key 任何 是否 转换 IDictionary string | 更新日期: 2023-09-27 18:32:31

假设我们有一个实现IDictionary<string, string>的类型。它叫MyStringDictionary.

我正在做一些属性/字段/方法反射,想知道该成员是否是我可以转换为IDictionary<string, object>的类型。

我知道typeof(IDictionary<string, string>).IsAssignableFrom(typeof(MyStringDictionary))是正确的,因为两个通用参数都匹配。但是,我不会直接分配给<string, string>而是转换为<string, object>,如下所示:

public class MyStringDictionary : IDictionary<string, string> {
   // Notice that the class itself has no generic type arguments!
}
MyStringDictionary myStringDict = GetBigDictionary();
IDictionary<string, object> genericDict = myStringDict
   .ToDictionary(kvp => kvp.Key, kvp => (object) kvp.Value);

如何确定此转换是否可行?

我在想我可以看看它是否实现了IEnumerable<KeyValuePair<,>>,但我再次受到这样一个事实的阻碍,即我不知道Value的类型参数,也不需要知道它,因为它只会被框object

确定类型是否可以转换为 IDictionary<string、object>,其中 Key 可以是任何类型

我在想我可以看看它是否实现了IEnumerable<KeyValuePair<,>>

当然,这是要走的路!现在有关如何执行此操作的详细信息:浏览myObj.GetType().GetInterfaces()的结果,并调用下面的方法。如果返回true,则第二个和第三个参数将设置为键类型和值的类型。

private static bool IsEnumKvp(Type t, out Type k, out Type v) {
    k = v = null;
    if (!t.IsGenericType) return false;
    var genDef = t.GetGenericTypeDefinition();
    if (genDef != typeof(IEnumerable<>)) return false;
    var itemType = t.GenericTypeArguments[0];
    if (!itemType.isGenericType) return false;
    var genItemDef = itemType.GetGenericTypeDefinition();
    if (genItemDef != typeof(KeyValuePair<,>)) return false;
    var kvpTypeArgs = genItemDef.GenericTypeArguments;
    k = kvpTypeArgs[0];
    v = kvpTypeArgs[1];
    return true;
}

MyStringDictionary上调用此方法应该会产生true

foreach (var t : MyStringDictionary.GetType().GetInterfaces()) {
    Type keyType, valType;
    if (IsEnumKvp(t, out keyType, out valType)) {
        Console.WriteLine(
            "Your class implements IEnumerable<KeyValuePair<{0},{1}>>"
        ,   keyType.FullName
        ,   valType.FullName
        );
    }
}

请注意,此方法可能会返回true多种类型。

相关文章: