简体   繁体   中英

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?

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<,>));

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM