【问题标题】:Determine if a type is convertible to IDictionary<string, object>, where Key can be any type确定一个类型是否可转换为 IDictionary<string, object>,其中 Key 可以是任何类型
【发布时间】:2016-05-06 15:12:15
【问题描述】:

假设我们有一个实现IDictionary&lt;string, string&gt; 的类型。它叫MyStringDictionary

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

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

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&lt;KeyValuePair&lt;,&gt;&gt;,但我又一次被我不知道Value 的类型参数的事实所困扰,也不需要知道因为它只会被装箱到object

【问题讨论】:

  • 哇,-1 已经是,发布后 0.2 秒!?!?!
  • @GrantWinney 我什至没有机会看到“0”:提交时,它已经有了-1。如果是你投票给我,谢谢!

标签: c# generics reflection type-conversion


【解决方案1】:

我在想我可以看看它是否实现了IEnumerable&lt;KeyValuePair&lt;,&gt;&gt;

当然,这就是要走的路!现在了解如何的详细信息:查看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 多种类型。

【讨论】:

  • 刚刚在两分钟前点击了GetInterfaces,并在GetGenericTypeDefinition 中迷惑不解,但被typeof(IDictionary&lt;,&gt;) 卡住了...哦,不是@987654332 @ 但== 因为我们处理的是Type 对象而不是这些类型的实例。
  • 所以你的答案可能可以直接用IDictionary&lt;,&gt;来简化,而不是检查IEnumerable&lt;&gt;然后KeyValuePair&lt;,&gt;,对吧?
  • @ErikE 使用IEnumerable&lt;KeyValuePair&lt;,&gt;&gt; 更通用,因为每个字典都是可枚举的,但不是每个可枚举的也是字典。
  • 嗯,区别在于IDictionary&lt;,&gt; 保证没有重复的Keys,但IEnumerable&lt;KeyValuePair&lt;,&gt;&gt; 没有。
  • @ErikE 这也是正确的:如果你知道你的输入是IDictionary,你就不需要在键上使用GroupBy
猜你喜欢
  • 1970-01-01
  • 2022-06-22
  • 1970-01-01
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
相关资源
最近更新 更多