通过搜索特定的通用接口参数获取实现通用接口的类型

时间:2017-12-12 18:03:49

标签: c# .net reflection

我想创建一个返回类型(或IEnumerable类型)的方法,该类型实现一个带有类型参数的特定接口 - 但是我想通过该泛型类型参数本身进行搜索。作为一个例子,这更容易证明:

我想要的方法签名:

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

然后如果我有下面的对象

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

然后我希望能够做到:

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

并获取包含FooRepoDifferentFooRepo类型的IEnumerable。

这与this question非常相似,但是使用该示例我想同时搜索IRepository<>User

2 个答案:

答案 0 :(得分:1)

你可以这样试试;

    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;
    }

<强>用法

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

答案 1 :(得分:1)

要重构@lucky的答案,我更喜欢将类型与通用类型定义进行比较,而不是使用类型名称:

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

或者,您可以检查是否可以从interf分配GenericIEnumerableType.MakeGenericType(typeof(T))或以其他方式分配