tags:

views:

119

answers:

2

I have a method that checks if a type is generic and then checks if the GenericTypeDefinition is of IEnumerable<>.

static Type GetEnumerableType(Type type)  
{  
    if(type.IsGenericType) {  
        var genericTypeDefinition = type.GetGenericTypeDefinition();  
        if (genericTypeDefinition == typeof(IEnumerable<>)) {  
            return type.GetGenericArguments()[0];  
        }  
    }  
    return null;  
}

Works like a charm if it is an IEnumerable. If the the GenericTypeDefinition is IList<> or List<> it doesn't work. I've tried..

typeof(IEnumerable<>).IsAssignableFrom(genericTypeDefinition)

..without success. Of course there must be a better way then chaining else-statements?

+3  A: 

I think the issue is you have your IsAssignableFrom statment backwards. I think you actually want genericTypeDefinition.IsAssignableFrom(typeof(IEnumerable<>))

I hate the IsAssignableFrom method, I recommend using this extension method instead.

public static bool IsA<T>(this Type type)
{
    return typeof (T).IsAssignableFrom(type);
}

So with extension method you would then do

bool validType = genericTypeDefinition.IsA<IEnumerable<>>();

Assuming this is the underlying problem it would explain why it works if it's directly IEnuerable but not other correct assignments since you were checking "IEnumberable<> is a List" which would be false.

Edit: Try just

static Type GetEnumerableType(Type type)  
{  
    if(type.IsA<IEnumerable<>>) {  
        {  
            return type.GetGenericArguments()[0];  
        }  
    }  
    return null;  
}
Chris Marisic
+1: For the IsA definition - that's a handy one.
Jon Cage
It doesn't solve the problem though. And, yes, I also often mistake the IsAssignableFrom method, but I don't think thats the case here.
Kenny Eliasson
Edited answer code
Chris Marisic
Your edit code with `if(type.IsA<IEnumerable<>>) { ` wont compile cause it wants a type argument.
Kenny Eliasson
I'd be a nitpicker and call the method something like 'IsOfType'. Why? Because 'Is a IEnumerable' doesn't sound right (should be Is an, but then it gets very tricky :P)In all seriousness though, I'm going to steal this extensionmethod. I like!
Erik van Brakel
@Erik: Good call :-)
Jon Cage
@Kenny wrap it with a typeof() statement
Chris Marisic
Open generics have such weird syntax, it's just a syntax issue.
Chris Marisic
+4  A: 

You can use GetInterfaces to check if a type implements IEnumerable<> like so

 Type type = new List<string>().GetType();
            if (type.IsGenericType)
            {
                var genericTypeDefinition = type.GetGenericTypeDefinition();

                if (genericTypeDefinition.GetInterfaces().Any( t => t.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
                {
                   return type.GetGenericArguments()[0];
                }
            }
Stan R.
Works perfectly.
Kenny Eliasson