反思,获取实现接口的类型,但不实现另一个接口

时间:2018-04-17 23:05:49

标签: c# reflection

我的API中有两种类型的存储库类:

同时拥有IRepository和IReportRepository的人:

internal class BuildingRepository : IBuildingRepository
public interface IBuildingRepository : IRepository<Building>, IReportRepository<BuildingReport>

那些只有IRepository的人:

internal class AppointmentRepository : IAppointmentRepository
public interface IAppointmentRepository : IRepository<Appointment>

如何返回仅实现IRepository而非IReportRepository的所有存储库。我认为会是这样的:

var repoInterfaceType = typeof(IRepository<>);
var reportRepo = typeof(IReportRepository<>);
var repoTypes = asm.GetTypes().Where(x =>
            !x.IsInterface && !x.IsAbstract && x.IsClass && 
            !x.IsGenericType && x.GetInterfaces().Any(y =>
                y.IsGenericType &&
                repoInterfaceType.IsAssignableFrom(y.GetGenericTypeDefinition()) && 
      !reportRepo.IsAssignableFrom(y.GetGenericTypeDefinition()))).ToList();

但它仍然让我回归。我错过了什么?

2 个答案:

答案 0 :(得分:1)

您的xs ++ [0]部分必须分成两个查询。因为,.Any(y => y.IsGenericType && repoInterfaceType.IsAssignableFrom(y.GetGenericTypeDefinition()) && !reportRepo.IsAssignableFrom(y.GetGenericTypeDefinition()))类是BuildingRepository的实现。此接口可从IRepository<Building>分配,不能从IRepository<>接口分配。在这种情况下,您的IReport<>条件会返回true。

您的Linq可以修改为:

Any

答案 1 :(得分:1)

您可以使用GetInterface(string)

大大缩短代码
var results = asm.GetTypes()
    .Where
    (
        t => t.GetInterface("IRepository`1") != null
          && t.GetInterface("IReportRepository`1") == null
    );

此LINQ将遍历所有类型并尝试检索两个感兴趣的接口。如果找不到该接口,则只返回null,所以我们只需要检查正确的接口是否为空而另一个是否为

如果你想知道我在哪里获得字符串&#34; IReportRepository`1&#34;,这就是mangled name,这是CLR在内部使用的字符串(你可以从堆栈识别它)转储)。如果您对使用字符串文字感到不舒服,可以在运行时从类型的Name属性中获取它,例如

var mangledName = typeof(IReportRepository<>).Name;