istrupin
istrupin

Reputation: 1533

Get type that implements generic interface by searching for a specific generic interface parameter

I'd like to create a method that returns a type (or IEnumerable of types) that implement a specific interface that takes a type parameter -- however I want to search by that generic type parameter itself. This is easier demonstrated as an example:

Method signature that I want:

 public IEnumerable<Type> GetByInterfaceAndGeneric(Type interfaceWithParam, Type specificTypeParameter)

And then if I have the below objects

  public interface IRepository<T> { };
  public class FooRepo : IRepository<Foo> { };
  public class DifferentFooRepo : IRepository<Foo> {};

I then want to be able to do:

  var repos = GetByInterfaceAndGeneric(typeof(IRepository<>), typeof(Foo));

and get an IEnumerable containing the types FooRepo and DifferentFooRepo.

This is very similar to this question, however using that example I would like to search by both IRepository<> and by User.

Upvotes: 7

Views: 1528

Answers (2)

Shimmy Weitzhandler
Shimmy Weitzhandler

Reputation: 104711

To refactor @lucky's answer, I prefer comparing the types with the generic type definition instead of using the type name:

static readonly Type GenericIEnumerableType = typeof(IEnumerable<>);

//Find all types that implement IEnumerable<T>
static IEnumerable<T> FindAllEnumerableTypes<T>(Assembly assembly) =>
  assembly
  .GetTypes()
  .Where(type =>
    type
      .GetInterfaces()
      .Any(interf =>
        interf.IsGenericType
        && interf.GetGenericTypeDefinition() == GenericIEnumerableType
        && interf.GenericTypeArguments.Single() == typeof(T)));

Alternatively, you can check if interf is assignable from GenericIEnumerableType.MakeGenericType(typeof(T)) or the other way around.

Upvotes: 5

Emre Kabaoglu
Emre Kabaoglu

Reputation: 13146

You can try like this;

    public static IEnumerable<Type> GetByInterfaceAndGeneric(Type interfaceWithParam, Type specificTypeParameter)
    {
        var query =  
            from x in specificTypeParameter.Assembly.GetTypes()
            where 
            x.GetInterfaces().Any(k => k.Name == interfaceWithParam.Name && 
            k.Namespace == interfaceWithParam.Namespace && 
            k.GenericTypeArguments.Contains(specificTypeParameter))
            select x;
        return query;
    }

Usage;

var types = GetByInterfaceAndGeneric(typeof(IRepository<>), typeof(Foo)).ToList();

Upvotes: 2

Related Questions