【问题标题】:Implementing ninject provider for a generic type为泛型类型实现 ninject 提供程序
【发布时间】:2019-11-03 06:53:01
【问题描述】:

使用 ninject,我想为依赖于 ApplicationDbContextMyRepository 类创建提供程序:

public class MyRepository<TEntity> : IMyRepository<TEntity>
    where TEntity : MyBaseEntity
{
    private ApplicationDbContext _dbContext;

    public MyRepository(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    // ...
}

我看到this document 解释了应该如何创建提供程序,但我不确定:

  1. 如何将ApplicationDbConext 参数传递给提供者
  2. 如何实例化泛型类型

这是我的尝试:

public class MyRepositoryProvider : Provider<MyRepository> 
{
    protected override MyRepository CreateInstance(IContext context)
    {
        // how to create a generic instance of type T?
        MyRepository myRepository = new MyRepository<T>(/*need ApplicationDbContext*/);
        return myRepository;
    }
}

我不确定是否可以为泛型类型创建提供程序。如果不, 有人可以展示如何使用Factory interface 做到这一点吗?


注意:我创建了this code review,解释了我为什么需要提供者。

【问题讨论】:

  • 1) bind IContextApplicationDbContext2) 使用 generic binding 时会发生什么,如下所述:stackoverflow.com/a/10243699/2877982
  • @aage:感谢您的评论。 IContext 是 ninject 的上下文(如 here 所述)。关于另一个链接,答案不是使用提供者...
  • 我知道它不是提供者,但为什么它与bindingresolving 的“常规”方式在container 中的工作方式有所不同?关于IContext... 可能只是将ApplicationDbContext 绑定到自身或factory

标签: c# dependency-injection ninject provider ninject-extensions


【解决方案1】:

因为在这种情况下,提供者知道目标实现类型。

然后,您可以从所请求的类型中获取泛型类型,并使用它来构造所需的实现。

public class MyRepositoryProvider : IProvider {
    private ApplicationDbContext _applicationDbContext;

    public MyRepositoryProvider(ApplicationDbContext applicationDbContext) {
        _applicationDbContext = applicationDbContext;
    }

    Type Type => typeof(MyRepository<>);

    public object Create(IContext context) {
        var genericArguments = context.GenericArguments; //TEntity
        var genericType = this.Type.MakeGenericType(genericArguments); //MyRepository<TEntity>

        //using reflection to do new MyRepository<TEntity>(_applicationDbContext)
        return Activator.CreateInstance(genericType, _applicationDbContext);
    }
}

Activator 在此使用是假设实现具有原始示例中的代码所暗示的公共构造函数。如果不公开,则可以使用反射来查找构造并调用它。

提供程序已向内核注册

kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind(typeof(IMyRepository<>)).ToProvider(typeof(MyRepositoryProvider)).InRequestScope();

告诉内核在解析抽象时使用提供者

IMyRepository<MyEntity> repository = kernel.Get<IMyRepository<MyEntity>>();

【讨论】:

    【解决方案2】:

    我设法为我的泛型类型创建了提供程序:

    public class MyRepositoryProvider<TEntity> : Provider<IMyRepository<TEntity>>
        where TEntity : MyBaseEntity
    {
        private ApplicationDbContext _applicationDbContext;
    
        public MyRepositoryProvider(ApplicationDbContext applicationDbContext)
        {
            _applicationDbContext = applicationDbContext;
        }
    
        protected override IMyRepository<TEntity> CreateInstance(IContext context)
        {
            return new MyRepository<TEntity>(_applicationDbContext);
        }
    }
    

    这就是绑定的样子:

    kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
    kernel.Bind(typeof(IMyRepository<>)).ToProvider(typeof(MyRepositoryProvider<>)).InRequestScope();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      • 1970-01-01
      • 2020-11-11
      相关资源
      最近更新 更多