Reputation: 1533
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
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
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