我正在尝试使用依赖项注入创建通用工厂,但似乎遇到了一个问题。
所以我有一个DataProvider<TModel,TId>
,看起来可能像这样:
public interface IDataProvider<TModel, TId>
where TModel:class, new()
{
TModel Get(TId id);
IEnumerator<TModel> Get();
TModel Create(TModel model);
TModel Update(TModel model);
int Delete(TId id);
}
我有一家看起来像
的工厂 public interface IDataProviderFactory
{
IDataProvider<TModel, TId> GetProvider<TModel,TId>() where TModel:class,new();
}
现在我的问题,
我想将IDataProvider<Customer,int>
添加到我想在哪里使用的构造器中。
我似乎无法弄清楚,但到目前为止我所拥有的是类似的东西
services.AddTransient(typeof(IDataProvider<,>), (serviceProvider)=>
{
var factory = serviceProvider.GetService<IDataProviderFactory>();
//I am not sure how to reference the type from above
return factory.GetProvider<>();
});
如何获取请求的类型并将其传递给factory.GetProvider<>()
方法?
答案 0 :(得分:1)
如代码示例所示,在MS.DI中不可能注册开放泛型函数。您将必须在开放通用抽象和开放通用实现之间进行映射,例如:
services.AddTransient(typeof(IDataProvider<,>), typeof(ProxyDataProvider<,>));
这当然将导致MS.DI负责创建ProxyDataProvider<,>
。但是您可以做的是使ProxyDataProvider<,>
成为将呼叫转发到IDataProviderFactory
的代理,它将再次控制数据提供者的创建。 DataProvider<,>
可以实现如下:
public class ProxyDataProvider<TModel, TId> : IDataProvider<TModel, TId>
where TModel:class, new()
{
private readonly IDataProviderFactory factory;
public ProxyDataProvider(IDataProviderFactory factory) =>
this.factory = factory;
private IDataProvider<TModel, TId> Provider =>
this.factory.GetProvider<TModel, TId>();
public TModel Get(TId id) => this.Provider.Get(id);
public IEnumerator<TModel> Get() => this.Provider.Get();
public TModel Create(TModel model) => this.Provider.Create(model);
public TModel Update(TModel model) => this.Provider.Update(model);
public int Delete(TId id) => this.Provider.Delete(id);
}
此外,您可以将工厂创建的数据提供程序缓存在代理内部。这样可以防止在每次调用时创建实例。另一方面,这将导致代理包含状态,因此使用AddScoped
注册它很重要:
services.AddScoped(typeof(IDataProvider<,>), typeof(ProxyDataProvider<,>));
答案 1 :(得分:0)
您可以注册通用类型,并且不使用工厂services.AddTransient(typeof(IDataProvider<,>), typeof(DataProvider<,>));
可以使用反射的另一种方法,但这不是使用反射的最佳方法。
顺便说一句,我建议您是否使用工厂,如果不只是将其删除,请在所有地方使用工厂