如何使用反射在 ASP.NET 核心中用自己的接口注册多个实现?
How to register multiple implementations with its own interface in ASP.NET Core using Reflection?
我是 ASP.NET Core 3.1 中的依赖注入的新手,我正在尝试使用反射创建我的存储库 类 的单例实例,但我无法将其用于工作。
目前,BookService
使用来自 DI 的 BookRepository
:
public class BookService : IBookService
{
private readonly IBookRepository _bookRepository;
public BookService(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
}
public async Task<Book> GetById(string id)
{
var find = await _bookRepository.FindAsync(id);
return find;
}
}
之所以有效,是因为我使用以下代码 (link to Microsoft Docs) 向容器添加了单例服务:
services.AddSingleton<IBookRepository, BookRepository>();
我正在尝试使用反射实现相同的结果。
BookRepository
public class BookRepository : BaseRepository<Book>, IBookRepository
{
}
IBookRepository
public interface IBookRepository : IAsyncRepository<Book>
{
}
这是我目前拥有的:
// Get all classes implementing IAsyncRepository
var repositoryTypes = assembly.GetTypes()
.Where(x => !x.IsInterface
&& x.GetInterface(typeof(IAsyncRepository<>).Name) != null);
foreach (var repositoryType in repositoryTypes)
{
// Adds a singleton service of BookRepository
services.AddSingleton(repositoryType);
}
但是如您所见,上面的代码仅添加了 BookRepository
,没有引用 IBookRepository
接口,因此它抛出了以下错误:
System.ArgumentException: 'Cannot instantiate implementation type 'IBookRepository' for service type 'IBookRepository'.'
Do you know how can I do that?
**EDIT:** This is the implementation I made to solve the problem:
``` c#
public static class DependencyInjectionExtensions
{
public static void AddApplicationServices(
this IServiceCollection services)
{
var assembly = Assembly.GetExecutingAssembly();
RegisterImplementationsOfServiceType(
services, assembly, typeof(IService));
RegisterImplementationsOfServiceType(
services, assembly, typeof(IAsyncRepository<>));
}
private static void RegisterImplementationsOfServiceType(
IServiceCollection services, Assembly assembly, Type type)
{
var implementationsType = assembly.GetTypes()
.Where(x => !x.IsInterface && x.GetInterface(type.Name) != null);
foreach (var implementationType in implementationsType)
{
var servicesType = implementationType.GetInterfaces()
.Where(r => !r.Name.Contains(type.Name));
foreach (var serviceType in servicesType)
{
services.AddSingleton(serviceType, implementationType);
}
}
}
}
像这样的东西会起作用
// Get all classes implementing IAsyncRepository
var repositoryTypes = assembly.GetTypes().Where(x => !x.IsInterface &&
x.GetInterface(typeof(IAsyncRepository<>).Name) != null);
foreach (var repositoryType in repositoryTypes)
{
var type = repositoryType.UnderlyingSystemType;
services.AddSingleton(type.GetInterface($"I{type.Name}"), type);
}
不知道有没有更好的获取接口类型的方法
我是 ASP.NET Core 3.1 中的依赖注入的新手,我正在尝试使用反射创建我的存储库 类 的单例实例,但我无法将其用于工作。
目前,BookService
使用来自 DI 的 BookRepository
:
public class BookService : IBookService
{
private readonly IBookRepository _bookRepository;
public BookService(IBookRepository bookRepository)
{
_bookRepository = bookRepository;
}
public async Task<Book> GetById(string id)
{
var find = await _bookRepository.FindAsync(id);
return find;
}
}
之所以有效,是因为我使用以下代码 (link to Microsoft Docs) 向容器添加了单例服务:
services.AddSingleton<IBookRepository, BookRepository>();
我正在尝试使用反射实现相同的结果。
BookRepository
public class BookRepository : BaseRepository<Book>, IBookRepository
{
}
IBookRepository
public interface IBookRepository : IAsyncRepository<Book>
{
}
这是我目前拥有的:
// Get all classes implementing IAsyncRepository
var repositoryTypes = assembly.GetTypes()
.Where(x => !x.IsInterface
&& x.GetInterface(typeof(IAsyncRepository<>).Name) != null);
foreach (var repositoryType in repositoryTypes)
{
// Adds a singleton service of BookRepository
services.AddSingleton(repositoryType);
}
但是如您所见,上面的代码仅添加了 BookRepository
,没有引用 IBookRepository
接口,因此它抛出了以下错误:
System.ArgumentException: 'Cannot instantiate implementation type 'IBookRepository' for service type 'IBookRepository'.'
Do you know how can I do that?
**EDIT:** This is the implementation I made to solve the problem:
``` c#
public static class DependencyInjectionExtensions
{
public static void AddApplicationServices(
this IServiceCollection services)
{
var assembly = Assembly.GetExecutingAssembly();
RegisterImplementationsOfServiceType(
services, assembly, typeof(IService));
RegisterImplementationsOfServiceType(
services, assembly, typeof(IAsyncRepository<>));
}
private static void RegisterImplementationsOfServiceType(
IServiceCollection services, Assembly assembly, Type type)
{
var implementationsType = assembly.GetTypes()
.Where(x => !x.IsInterface && x.GetInterface(type.Name) != null);
foreach (var implementationType in implementationsType)
{
var servicesType = implementationType.GetInterfaces()
.Where(r => !r.Name.Contains(type.Name));
foreach (var serviceType in servicesType)
{
services.AddSingleton(serviceType, implementationType);
}
}
}
}
像这样的东西会起作用
// Get all classes implementing IAsyncRepository
var repositoryTypes = assembly.GetTypes().Where(x => !x.IsInterface &&
x.GetInterface(typeof(IAsyncRepository<>).Name) != null);
foreach (var repositoryType in repositoryTypes)
{
var type = repositoryType.UnderlyingSystemType;
services.AddSingleton(type.GetInterface($"I{type.Name}"), type);
}
不知道有没有更好的获取接口类型的方法