I\'ve got a generic method:
Func, bool> CreateFunction()
where T
can be any number of diff
You could 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");
}
}
}
You can avoid using ugly and potentially risky type name string checking using the IsGenericType and GetGenericTypeDefinition members, 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
}
The easy 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 (throws an exception) if T
implements more than one IDictionary<,>
interface, but that will probably be fine for your purposes.
For the sake of completeness, here's an implementation that will work on types with multiple IDictionary<,>
interfaces by using the first one:
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 routine t
is an object, whereas T
is a type in the first routine.
I think that if you call Type.GetGenericTypeDefinition() that should return the "base" generic type used to construct the concrete Type.
Note that just comparing this to IDictionary<,>
is likely not enough, because if someone passes in an instance of Dictionary<,>
I assume you would want to use that, as well. You could either check to see if the Type implements IDictionary<,>
or you might be able to call Type.IsAssignableFrom(), although based on the doc I'm not sure how well this would work with generic Types.