如何使用反射向接口注册通用服务

问题描述 投票:0回答:1

我有多个具有这种模式的服务,每个存储库类都使用泛型作为上下文,并且也使用泛型实现一个接口:

public partial interface IUserRepository<TContext> : IRepository<TContext, UserRow> where TContext : DbContext
{
}

public partial class UserRepository<TContext> : RepositoryBase<TContext, UserRow>, IUserRepository<TContext> where TContext : DbContext
{
}

我可以手动注册我的服务,但它不可扩展,因为我将拥有数十个服务:

services.AddScoped<IUserRepository<DatabaseApiDbContext>, UserRepository<DatabaseApiDbContext>>();
services.AddScoped<IUserRepository<DatabaseApiDbContextSandbox>, UserRepository<DatabaseApiDbContextSandbox>>();

我想我可以简化注册吗?我不确定这是否有效,但类似这样:

services.AddScoped(typeof(IUserRepository<>), typeof(UserRepository<>));

但这仍然需要为每个存储库编写一行代码。

问题

我想使用反射来注册我的存储库。例如:

  1. 获取程序集中继承泛型 RepositoryBase 类的所有类(例如 XYZRepository<>)
  2. 对于每个类别
  • 获取其对应的 Repository 接口的类型(例如 IXYZRepository<>)
  • 使用相应的
    XYZRepository<>
    接口注册
    IXYZRepository<>

但我的反思能力不足以实现这一目标。感谢您的帮助!

c# .net-core dependency-injection reflection .net-6.0
1个回答
-2
投票

假设当前执行的程序集中存在实现类:

Assembly.GetExecutingAssembly()
.GetTypes()
.Where(a => a.Name.EndsWith("Repository") && !a.IsAbstract && !a.IsInterface)
.Select(a => new { assignedType = a, serviceTypes = a.GetInterfaces().ToList() })
.ToList()
.ForEach(typesToRegister =>
{
    typesToRegister.serviceTypes.ForEach(typeToRegister => services.AddScoped(typeToRegister, typesToRegister.assignedType));
});

同样,您也可以使用反射找到 DbContext 类型并枚举以为类型和接口制作泛型类型参数。

您可以看看以下文章: https://www.crispy-engineering.com/p/registering-all-types-as-generic-interfaces-in-assemble-in-dotnet-core

问候 马苏德

© www.soinside.com 2019 - 2024. All rights reserved.