3

I'm working on a custom JsonConverter, and override the CanConvert-method.

public override bool CanConvert(Type objectType)
{
    return (typeof(IDictionary).IsAssignableFrom(objectType) ||
            TypeImplementsGenericInterface(objectType, typeof(IDictionary<,>)));
}

private static bool TypeImplementsGenericInterface(Type concreteType, Type interfaceType)
{
    return concreteType.GetInterfaces()
           .Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == interfaceType);
}

Very much inspired from this answer. The thing is that I only want to return true if the key of the dictionary is of a specific type. For example, I only want to return true if the key is of type Bar, or inherits/implements Bar. The value doesn't matter. The value can be of any type.

Dictionary<string, int> // false
Dictionary<Bar, string> // true
Dictionary<Foo, string> // false
Dictionary<Bar, Foo> // true
Dictionary<BarSubClass, Foo> // true

How can I, from a Type, detect if it's a Dictionary and the key is assignable from a specific type?

What I've tried so far:

typeof(IDictionary<Bar, object>).IsAssignableFrom(objectType)

Unfortunately this returns false.

smoksnes
  • 10,509
  • 4
  • 49
  • 74
  • Possible duplicate of [Testing if an Object is a Dictionary in C#](https://stackoverflow.com/questions/123181/testing-if-an-object-is-a-dictionary-in-c-sharp) – DerApe Aug 03 '17 at 06:15
  • @derape - The difference is that I don't have an instance. I have a type. Also, I already know how to check if it's assignable from Dictionary. I need to check if it has a specific key as well. – smoksnes Aug 03 '17 at 06:18
  • You'll have to dig into the interface definitions [Generic Arguments](https://msdn.microsoft.com/en-us/library/system.type.getgenericarguments(v=vs.110).aspx) – Andrés Robinet Aug 03 '17 at 06:20
  • @smoksnes you don't need an instance to do that, just the type – DerApe Aug 03 '17 at 06:39

1 Answers1

4

You have to check the generic type and the first type argument (TKey):

concreteType.GetInterfaces().Any(i => i.IsGenericType &&
    (i.GetGenericTypeDefinition() == typeof(IDictionary<,>)) &&
    typeof(Bar).IsAssignableFrom(i.GetGenericArguments()[0]));
Sefe
  • 13,731
  • 5
  • 42
  • 55