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



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

那些同时具有 IRepository 和 IReportRepository 的人:

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

而那些只有独立性的:

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

但它仍然让我俩都回来了。我错过了什么?

您可以使用 GetInterface(字符串(大大缩短代码:

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

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

如果您想知道我从哪里得到字符串"IReportRepository'1",这被称为损坏的名称,这是 CLR 内部使用的字符串(您可以从堆栈转储中识别它(。如果您不喜欢使用字符串文本,可以在运行时从类型的 Name 属性获取它,例如

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

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

可以按如下方式修改 Linq:

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

最新更新