1

I have a property on my ViewModel that is of type IDictionary<string, string>. I am going through the list of properties on that ViewModeland using reflection to determine if it is a dictionary.

Currently I have:

if (typeof(IDictionary).IsAssignableFrom(propDescriptor.PropertyType))

However, that is always false because propDescriptor.PropertyType is IDictionary`2. Any ideas how I can get that to work? Also, why isn't that working?


I just changed my property to be IDictionary instead of IDictionary.

EDIT: Not sure where my generics went, but the second IDictionary in the sentence above has string, string.

casperOne
  • 73,706
  • 19
  • 184
  • 253
g.t.w.d
  • 601
  • 1
  • 10
  • 30
  • Should it not then be if (typeof(IDictionary).IsAssignableFrom(propDescriptor.PropertyType)) – stuartd Jan 17 '13 at 13:59
  • I need it to be generic, so I can't do that. – g.t.w.d Jan 17 '13 at 14:02
  • How about http://stackoverflow.com/questions/3765859/is-there-a-way-to-determine-if-a-generic-type-is-built-from-a-specific-generic-t – stuartd Jan 17 '13 at 14:05
  • Don't change the property type to the non-generic interface. Actually, don't use non-generic interfaces from .NET 1 when there are new generic interfaces that supersede them. – Jeppe Stig Nielsen Jan 17 '13 at 14:15

4 Answers4

5

The reason why it's not working is that the generic IDictionary<,> interface does not have the non-generic IDictionary as a base interface.

Maybe this is what you want:

var type = propDescriptor.PropertyType;
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>))
{ // ...

Edit: The above code will only check if type is declared as IDictionary<X, Y> for some X and Y. If you also want to handle cases where type represents a class or struct that implements IDictionary<X, Y> (or even an interface derived from IDictionary<X, Y>), then try this:

Func<Type, bool> isGenericIDict =
  t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IDictionary<,>);
var type = propDescriptor.PropertyType;
if (isGenericIDict(type) || type.GetInterfaces().Any(isGenericIDict))
{ // ..
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
1

It's not IDictionary`2. It's the compiler-generated class name for a generic IDictionary<TKey,TValue>, which is not directly castable to an IDictionary.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
D Stanley
  • 149,601
  • 11
  • 178
  • 240
1

IDictionary`2 is not derived from IDictionary as can be seen in its definition:

public interface IDictionary<TKey, TValue> :
    ICollection<KeyValuePair<TKey, TValue>>,
    IEnumerable<KeyValuePair<TKey, TValue>>,
    IEnumerable

Therefore the generic IDictionary<TKey, TValue> is not castable to IDictionary.

Adi Lester
  • 24,731
  • 12
  • 95
  • 110
  • I guess my question is, why is it doing IDictionary`2? Also, when I do this: var dictionary = propDescriptor.GetValue(instance) as IDictionary; It works and gives me the value. I don't understand why that would work and the type check wouldn't. – g.t.w.d Jan 17 '13 at 14:02
  • You should differentiate between the `IDictionary` interface, which doesn't derive from `IDictionary` and the `Dictionary` class which does implement `IDictionary`. – Adi Lester Jan 17 '13 at 14:06
  • That only works because `Dictionary<,>` implements `IDictionary` and `IDictionary<,>`, but `IDictionary<,>` does not implement `IDictionary`. – odyss-jii Jan 17 '13 at 14:09
0

IDictionary is different from IDictionary< T, K >.

Use:

if (typeof(IDictionary<string, string>).IsAssignableFrom(propDescriptor.PropertyType))
lante
  • 7,192
  • 4
  • 37
  • 57