Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a type implements a generic interface without considering the generic type arguments

I have an interface

public interface MyInterface<TKey, TValue>
{
}

Implementations are irrelevant. Now I want to check if a given type is an implementation of that interface. This method fails for

public class MyClass : MyInterface<int, string>
{
}

But I don't know how to do the check.

public void CheckIfTypeImplementsInterface(Type type)
{
    var result1 = typeof(MyInterface<,>).IsAssignableFrom(type); --> false
    var result2 = typeof(MyInterface<int,string>).IsAssignableFrom(type); --> true
}

What do I have to do for result1 to be true?

like image 203
Jürgen Steinblock Avatar asked Aug 14 '13 13:08

Jürgen Steinblock


Video Answer


2 Answers

As far as I know, the only way to do this is to get all interfaces and see if the generic definition matches the required interface type.

bool result1 = type.GetInterfaces()
    .Where(i => i.IsGenericType)
    .Select(i => i.GetGenericTypeDefinition())
    .Contains(typeof(MyInterface<,>));

EDIT: As Jon points out in the comments, you could also do:

bool result1 = type.GetInterfaces()
    .Where(i => i.IsGenericType)
    .Any(i => i.GetGenericTypeDefinition() == typeof(MyInterface<,>));
like image 162
Lee Avatar answered Sep 30 '22 07:09

Lee


Generally, such behavior is only required in cases where an interface contains some functionality which does not depend upon the generic type parameters. If you have control over the interfaces, the best solution is to have the type-dependent parts inherit from a non-type dependent part. For example, if the existing collection interfaces didn't exist, one might define them something like:

interface ICountable 
  { CollectionAttribute Attributes {get;} int Count {get;} }
interface ICollection<T> : IEnumerable<T> ICountable
  { ... and other stuff ... }

Had such a thing been done with ICollection, then code which was expecting an IEnumerable<Animal> but got an object of type CatList that just implements IList<Cat> would have no problem using the Count member of that object (note that List<Animal> implements the non-generic ICollection, but other IList<Animal> implementations may not).

As it is, if you're stuck with the task of having code somehow find the Count method of ICollection<Cat> when you're expecting an IEnumerable<Animal>, it may be worthwhile to build something like a Dictionary<Type, Func<IEnumerable<Animal>, int> so that once you've found that CatList implements ICollection<Cat>.Count you can construct a delegate to a method which will cast its argument to ICollection<Cat>, call Count on it, and return its result. If you have such a dictionary, then if you're given another CatList you'll be able to simply invoke the delegate from the dictionary.

like image 44
supercat Avatar answered Sep 30 '22 05:09

supercat