在C#中测试对象是否为字典

时间:2020-03-06 14:37:16  来源:igfitidea点击:

有没有一种方法可以测试对象是否为字典?

在一种方法中,我尝试从列表框中的选定项目中获取值。在某些情况下,列表框可​​能绑定到字典,但这在编译时未知。

我想做类似的事情:

if (listBox.ItemsSource is Dictionary<??>)
{
    KeyValuePair<??> pair = (KeyValuePair<??>)listBox.SelectedItem;
    object value = pair.Value;
}

有没有办法在运行时使用反射来动态地执行此操作?我知道可以将反射与泛型类型一起使用并确定键/值参数,但是我不确定在检索到这些值之后是否有办法进行其余操作。

解决方案

检查它是否实现IDictionary。

请参阅System.Collections.IDictionary的定义,以了解给我们带来了什么。

if (listBox.ItemsSource is IDictionary)
{
    DictionaryEntry pair = (DictionaryEntry)listBox.SelectedItem;
    object value = pair.Value;
}

编辑:
当我意识到KeyValuePair不能转换为DictionaryEntry时的替代方法

if (listBox.DataSource is IDictionary)
{
     listBox.ValueMember = "Value";
     object value = listBox.SelectedValue;
     listBox.ValueMember = ""; //If you need it to generally be empty.
}

该解决方案使用反射,但是在这种情况下,我们不必做繁琐的工作,ListBox会为我们完成。同样,如果我们通常将字典作为数据源,则可以避免一直都重置ValueMember。

我们可以稍微通用一些,然后询问它是否实现了" IDictionary"。然后,KeyValue集合将使用普通的"对象"。

我们可以检查它是否实现IDictionary。我们只需要枚举使用DictionaryEntry类。

它应该类似于以下内容。我将此内容写在答案框中,因此语法可能并不完全正确,但是我已将其设置为Wiki可编辑的,以便任何人都可以修复。

if (listBox.ItemsSource.IsGenericType && 
    typeof(IDictionary<,>).IsAssignableFrom(listBox.ItemsSource.GetGenericTypeDefinition()))
{
    var method = typeof(KeyValuePair<,>).GetProperty("Value").GetGetMethod();
    var item = method.Invoke(listBox.SelectedItem, null);
}

我相信已经有警告了。

当测试对象"是"某物或者某物时,我们正在重新实现类型系统(的一部分)。第一个"是"通常紧随其后,第二个很快,然后代码中充满了类型检查,至少在面向对象设计中,类型系统应该能够很好地处理这些检查。

当然,我对这个问题的背景一无所知。我确实知道我们自己的代码库中有2000行文件,该文件可处理50种不同的对象到字符串的转换... :(

if(typeof(IDictionary).IsAssignableFrom(listBox.ItemsSource.GetType()))
{

}