Is there a way to determine if a generic type is generated from a particular generic type definition?

I have a general method:

Func<IEnumerable<T>, bool> CreateFunction<T>() 

where T can be any number of different types. This method uses a bunch of material using reflection, and if T is an IDictionary , regardless of the TKey and TValue I need to execute certain dictionary code.

Thus, the method could be called:

 var f = CreateFunction<string>(); var f0 = CreateFunction<SomePocoType>(); var f1 = CreateFunction<IDictionary<string,object>>(); var f2 = CreateFunction<Dictionary<string,object>>(); var f3 = CreateFunction<SomeDerivedDictionaryType<string,object>>(); 

and etc.

Clarification in @Andy's answer

Ultimately, I want to know if T inherits from / implements IDictionary , even if T itself is a Dictionary or some other type that derives from this interface.

 if(typeof(T) == typeof(IDictionary<,>) 

does not work because T is a generic type, not a definition of a generic type.

And without knowing TKey and TValue (which are unknown at compile time), I can’t compare with any particular type that I would know before runtime.

The only thing I came up with was to look at the type name or check its method with reflection, looking for methods that would make me believe that this is a dictionary (i.e. look for ContainsKey and get_Item ).

Is there an easy way to make such a definition?

+4
source share
4 answers

You can do something like

 class Program { static void Main(string[] args) { Example<IDictionary<int, string>>.IsDictionary(); Example<SortedDictionary<int, string>>.IsDictionary(); Example<Dictionary<int, string>>.IsDictionary(); Console.ReadKey(); } } public class Example<T> { public static void IsDictionary() { if (typeof(T).GetInterface(typeof(IDictionary<,>).Name) != null || typeof(T).Name.Contains("IDictionary")) { Console.WriteLine("Is IDictionary"); } else { Console.WriteLine("Not IDictionary"); } } } 
+2
source

You can avoid using an ugly and potentially risky type string string check with IsGenericType and GetGenericTypeDefinition , as follows:

 var type = typeof (T); if (typeof (IDictionary).IsAssignableFrom(type)) { //non-generic dictionary } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (IDictionary<,>)) { //generic dictionary interface } else if (type.GetInterfaces().Any( i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof (IDictionary<,>))) { //implements generic dictionary } 
+7
source

A simple way is just this:

 Type iDict = null; if (typeof(T).GetGenericTypeDefinition() == typeof(IDictionary<,>)) iDict = typeof(T); else iDict = typeof(T).GetInterface(typeof(IDictionary<,>).Name); if (iDict != null) { var genericParams = iDict.GetGenericArguments(); Type tKey = genericParams[0], tValue = genericParams[1]; } 

Note that this will not work (throwing an exception) if T implements more than one IDictionary<,> interface, but this will probably be good for your purposes.

For completeness, here is an implementation that will work with types with multiple IDictionary<,> interfaces, using the first:

 Type iDict = t.GetType().GetInterfaces() .Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IDictionary<,>)) .FirstOrDefault(); if (iDict != null) { var genericParams = iDict.GetGenericArguments(); Type tKey = genericParams[0], tValue = genericParams[1]; } 

Note that in this second subroutine, T is an object, while T is a type in the first procedure.

+4
source

I think that if you call Type.GetGenericTypeDefinition () , which should return the base generic type used to build the particular type.

Note that simply comparing this to IDictionary<,> is most likely not enough, because if someone passes an instance of Dictionary<,> , I assume that you also want to use it. You can either check that Type implements IDictionary<,> , or you can call Type.IsAssignableFrom () , although based on doc I'm not sure how well this will work with generic types.

0
source

All Articles