Я знаю, что этот вопрос был задан вопрос много лет назад, но до сих пор видны публично.
Существовали несколько примеров предложенных здесь в этой теме, и в этом одна:
Determine if type is dictionary [duplicate]
но есть несколько несовпадений, поэтому я хочу поделиться своим решением
Короткий ответ:
var dictionaryInterfaces = new[]
{
typeof(IDictionary<,>),
typeof(IDictionary),
typeof(IReadOnlyDictionary<,>),
};
var dictionaries = collectionOfAnyTypeObjects
.Where(d => d.GetType().GetInterfaces()
.Any(t=> dictionaryInterfaces
.Any(i=> i == t || t.IsGenericType && i == t.GetGenericTypeDefinition())))
Дольше ответа:
Я считаю, что это является причиной того, почему люди делают ошибки:
//notice the difference between IDictionary (interface) and Dictionary (class)
typeof(IDictionary<,>).IsAssignableFrom(typeof(IDictionary<,>)) // true
typeof(IDictionary<int, int>).IsAssignableFrom(typeof(IDictionary<int, int>)); // true
typeof(IDictionary<int, int>).IsAssignableFrom(typeof(Dictionary<int, int>)); // true
typeof(IDictionary<,>).IsAssignableFrom(typeof(Dictionary<,>)); // false!! in contrast with above line this is little bit unintuitive
так пусть у нас есть эти типы:
public class CustomReadOnlyDictionary : IReadOnlyDictionary<string, MyClass>
public class CustomGenericDictionary : IDictionary<string, MyClass>
public class CustomDictionary : IDictionary
и эти экземпляры:
var dictionaries = new object[]
{
new Dictionary<string, MyClass>(),
new ReadOnlyDictionary<string, MyClass>(new Dictionary<string, MyClass>()),
new CustomReadOnlyDictionary(),
new CustomDictionary(),
new CustomGenericDictionary()
};
так что если мы будем использовать .IsAssignableFrom():
var dictionaries2 = dictionaries.Where(d =>
{
var type = d.GetType();
return type.IsGenericType && typeof(IDictionary<,>).IsAssignableFrom(type.GetGenericTypeDefinition());
}); // count == 0!!
мы не получим ни одного случая
так лучший способ, чтобы получить все интерфейсы и проверить, если любой из них является интерфейс приложения:
var dictionaryInterfaces = new[]
{
typeof(IDictionary<,>),
typeof(IDictionary),
typeof(IReadOnlyDictionary<,>),
};
var dictionaries2 = dictionaries
.Where(d => d.GetType().GetInterfaces()
.Any(t=> dictionaryInterfaces
.Any(i=> i == t || t.IsGenericType && i == t.GetGenericTypeDefinition()))) // count == 5
Um, вы знаете IDictionary фактически не реализует интерфейс IDictionary ? Таким образом, это не будет работать для общих словарей. Посмотрите на http://msdn.microsoft.com/en-us/library/s4ys34ea.aspx –
2008-09-23 19:32:36
Кроме того, даже если это был словарь, который реализует IDictionary, тогда он реализует IEnumerable >, поэтому я ожидаю, что case to DictionaryEntry для отказа. –
2008-09-23 19:39:05
Конечно, я имел в виду «бросить в DictionaryEntry» выше. – 2008-09-23 19:44:31