mad*_*dd0 5 c# dependency-injection .net-core asp.net-core
我有一个用例,其中我想使用.NET Core依赖项注入创建存储库实例,但需要在运行时更改构造函数参数之一。确切地说,应在运行时确定的参数是“数据库连接”,它将指向由调用者确定的一个或另一个数据库。顺便说一下,该类型未在DI容器中注册,但其他所有类型都已注册。
调用者将使用存储库工厂类型来创建具有所需连接的存储库。
看起来像这样:
class ARepository : IARepository
{
public ARepository(IService1 svc1, IService2 svc2, IConnection connection) { }
public IEnumerable<Data> GetData() { }
}
class RepositoryFactory : IRepositoryFactory
{
public RepositoryFactory(IServiceProvider serviceProvider) =>
_serviceProvider = serviceProvider;
public IConnection CreateAlwaysFresh<TRepository>() =>
this.Create<TRepository>(new FreshButExpensiveConnection());
public IConnection CreatePossiblyStale<TRepository>() =>
return this.Create<TRepository>(new PossiblyStaleButCheapConnection());
private IConnection Create<TRepository>(IConnection conn)
{
// Fails because TRepository will be an interface, not the actual type
// that I want to create (see code of AService below)
return ActivatorUtilities.CreateInstance<TRepository>(_serviceProvider,conn);
// Fails because IConnection is not registered, which is normal
// because I want to use the instance held in parameter conn
return _serviceProvider.GetService<TRepository>();
}
}
Run Code Online (Sandbox Code Playgroud)
登记了以下类型:
services.AddTransient<IARepository, ARepository>(); // Probably not needed
services.AddTransient<IService1, Service1>();
services.AddTransient<IService2, Service2>();
services.AddTransient<IRepositoryFactory, RepositoryFactory>();
Run Code Online (Sandbox Code Playgroud)
工厂将这样使用:
services.AddTransient<IARepository, ARepository>(); // Probably not needed
services.AddTransient<IService1, Service1>();
services.AddTransient<IService2, Service2>();
services.AddTransient<IRepositoryFactory, RepositoryFactory>();
Run Code Online (Sandbox Code Playgroud)
我之所以保留所有基于接口的代码的原因之一,当然是用于单元测试。但是,正如您从的伪实现中可以看到的那样RepositoryFactory.Create<TRepository>,这也是一个问题,因为我达到了需要这样做的地步:
确定IARepository要传递给DI容器中与之关联的concret类型ActivatorUtilities,以便在使用或IConnection解析其他构造函数参数时使用期望的值创建它的实例。IServiceProvider
以某种方式告诉获得特定服务时IServiceProvider使用特定实例IConnection
使用.NET Core DI完全可以吗?
(奖金问题:我应该使用其他更简单的方法吗?)
更新:我对示例代码进行了一些编辑,以期使我的意图更加清楚。这个想法是允许相同的存储库,完全相同的代码根据调用者的特定需求使用不同的连接(在应用程序启动期间配置)。总结一下:
在工厂中注入正确连接的问题有几种解决方法:
由于IConnectionDI 不会创建,您可以从存储库构造函数中将其删除并将其作为属性,然后在工厂上您可以在创建后分配其值:
interface IARepository
{
IConnection Connection { set; }
}
class ARepository : IARepository
{
public IConnection Connection { private get; set; }
public ARepository(IService1 svc1, IService2 svc2)
{ /* ... */ }
}
class RepositoryFactory : IRepositoryFactory
{
/* ... */
private IConnection Create<TRepository>(IConnection conn)
where TRepository : IARepository
{
var svc = _serviceProvider.GetService<TRepository>();
svc.Connection = conn;
return svc;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
425 次 |
| 最近记录: |