获取字典的键值对而不知道其类型

8
我有一个名为“instance”的对象。
instance.GetType().GetGenericTypeDefinition() == typeof(Dictionary<,>)

是真的。我的问题是,我如何从这个对象中提取键值对,而不实际知道它们的通用类型?我想得到类似于KeyValuePair<object, object>[]的东西。请注意,我还知道字典在运行时使用的泛型类型(但不是编译时)。我假设需要某种反射?

后续:是否有一般机制将object转换为SomeClass<>(如果我知道这是正确的类型),并因此使用它,而不受泛型参数类型的影响?


或者非泛型的 IDictionary 接口。 - SLaks
这是一个很好的观点。我正在寻找一个特定于 Dictionary<,> 的答案,但我想知道是否有一种方法可以动态地转换任何需要泛型参数的对象,以便我可以使用它。 - nickolayratchev
IDictionary的ToList方法返回一个KeyValuePair列表:var keyValuePairList = instance.ToList();。这是你想要的吗(在你的后续操作之前)?还是我漏掉了什么? - Steven Wexler
@steaks 我认为这种方法的问题在于他有一个“对象”,他知道它是某种“Dictionary<K,V>”,但他不知道“K”和“V”是什么。因此,在他能够获得包含正确类型的字典转换后的变量之前,他无法调用.ToList(),而这需要在运行时构造。 - Jeremy Todd
你为什么可以知道你得到了一个字典,但不能同时使用类型系统呢?如果你无法通过函数的参数知道你正在获取一个字典,那么你应该重新考虑你的设计。 - siride
@siride 或许这些字典被存储在某个接受通用对象(例如Winforms控件)的东西中。我只是试图为通用代码做类似的事情,以便与一些列表框一起使用。它们中的每一个都是从模型返回的Dictionary<int,V>填充的,其中V可能会变化。填充列表框的函数只需将此字典作为IEnumerable(循环遍历时给出KeyValuePairs)即可。我面临的挑战是在我的通用函数中获取当前选定项的键的问题。最终,dynamic起了作用。 - Stewart
3个回答

7

我会采纳Jeremy Todd的建议,只不过可能会缩短一点:

    foreach(var item in (dynamic)instance)
    {
       object key = item.Key;
       object val = item.Value;
    }

另外(不确定是否有帮助),您可以通过以下方式获取参数的类型:

Type[] genericArguments = instance.GetType().GetGenericArguments();

我想补充一点,使用动态语言也可以通过索引器语法检索值:(myDictonary as dynamic)["someKeyValue"] - Protector one
有没有任何想法可以在不使用“dynamic”的情况下完成这个任务?我被困在.NET 3.5中,而显然直到4.0才加入了“dynamic”。 - gman

5

对于快速解决方案,您可以直接使用dynamic

Dictionary<string, int> myDictionary = new Dictionary<string, int>();

myDictionary.Add("First", 1);
myDictionary.Add("Second", 2);
myDictionary.Add("Third", 3);

dynamic dynamicDictionary = myDictionary;

foreach (var entry in dynamicDictionary)
{
  object key = entry.Key;
  object val = entry.Value;
  ...whatever...
}

1
没有办法解决这个问题而不绕过类型系统,因为在编译时无法确定类型。任何解决方案都将涉及到像 dynamic 或反射之类的东西,而其中 dynamic 更加优雅。 - Jeremy Todd
那么对于这个问题更好的回答应该是 - “重新设计你的解决方案?” 你能展示一下你的解决方案吗?你怎么知道他的问题到底是什么?我讨厌那种回答。 - Dimitar Dimitrov
@siride:我同意通常会尽量避免使用“动态”解决方案,但我认为那样有点太苛刻了。至于场景,考虑一下如果您尝试序列化一个字典会发生什么。您需要能够序列化任何类型的字典——您如何将解决方案概括? - nickolayratchev
@NickolayRatchev:这就是为什么我们有泛型、接口和包装类来处理类型特定的细节。让类型本身序列化自己。 - siride

1
这是我想到的帮助自己的方法。那时它满足了我的需求...或许可以帮助其他人。
foreach (var unknown in (dynamic)savedState)
{
  object dKey = unknown.Key;
  object dValue = unknown.Value;

  switch (dKey.GetType().ToString())
  {
    case "System.String":
      //Save the key
      sKey = (string)dKey;

      switch (dValue.GetType().ToString())
      {
        case "System.String":
          //Save the string value
          sValue = (string)dValue;

          break;
        case "System.Int32":
          //Save the int value
          sValue = ((int)dValue).ToString();

          break;
      }

      break;
  }

  //Show the keypair to the global dictionary
  MessageBox.Show("Key:" + sKey + " Value:" + sValue);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接