Reputation: 3698
I'm doing a heavy bit of reflection in my current project, and I'm trying to provide a few helper methods just to keep everything tidy.
I'd like to provide a pair of methods to determine if a type or instance implements IEnumerable
– regardless of the type T
. Here is what I have at the moment:
public static bool IsEnumerable(this Type type)
{
return (type is IEnumerable);
}
public static bool IsEnumerable(this object obj)
{
return (obj as IEnumerable != null);
}
When I test them using
Debug.WriteLine("Type IEnumerable: " + typeof(IEnumerable).IsEnumerable());
Debug.WriteLine("Type IEnumerable<>: " + typeof(IEnumerable<string>).IsEnumerable());
Debug.WriteLine("Type List: " + typeof(List<string>).IsEnumerable());
Debug.WriteLine("Type string: " + typeof(string).IsEnumerable());
Debug.WriteLine("Type DateTime: " + typeof(DateTime).IsEnumerable());
Debug.WriteLine("Instance List: " + new List<string>().IsEnumerable());
Debug.WriteLine("Instance string: " + "".IsEnumerable());
Debug.WriteLine("Instance DateTime: " + new DateTime().IsEnumerable());
I get this as the result:
Type IEnumerable: False
Type IEnumerable<>: False
Type List: False
Type string: False
Type DateTime: False
Instance List: True
Instance string: True
Instance DateTime: False
The type method doesn't appear to work at all – I had expected a true
for the direct System.Collections.IEnumerable
match at least.
I'm aware that string
is technically enumerable, albeit with a few caveats. Ideally in this case, however, I'd need the helper method to return false
for it. I just need the instances with a defined IEnumerable<T>
type to return true
.
I've probably just missed something fairly obvious – can anyone point me in the right direction?
Upvotes: 61
Views: 52548
Reputation: 2958
To check if some type implements IEnumerable regardless of T one needs to check the GenericTypeDefinition.
public static bool IsIEnumerableOfT(this Type type)
{
return type.GetInterfaces()
.Append(type) // ensure this type is also checked
.Any(x => x.IsGenericType
&& x.GetGenericTypeDefinition() == typeof(IEnumerable<>));
}
Upvotes: 24
Reputation: 8816
In addition to Type.IsAssignableFrom(Type)
, you can also use Type.GetInterfaces()
:
public static bool ImplementsInterface(this Type type, Type interfaceType)
{
// Deal with the edge case
if ( type == interfaceType)
return true;
bool implemented = type.GetInterfaces().Contains(interfaceType);
return implemented;
}
That way, if you wanted to check multiple interfaces you could easily modify ImplementsInterface
to take multiple interfaces.
Upvotes: 17
Reputation: 28157
The following line
return (type is IEnumerable);
is asking "if an instance of Type
, type
is IEnumerable
", which clearly it is not.
You want to do is:
return typeof(IEnumerable).IsAssignableFrom(type);
Upvotes: 96