DotNet核心依赖注入工厂类型

时间:2020-08-27 13:32:47

标签: c# .net-core dependency-injection

我正在尝试使用依赖项注入创建通用工厂,但似乎遇到了一个问题。

所以我有一个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<>()方法?

2 个答案:

答案 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<,>)); 可以使用反射的另一种方法,但这不是使用反射的最佳方法。 顺便说一句,我建议您是否使用工厂,如果不只是将其删除,请在所有地方使用工厂