如何配置Ninject以便根据先前注入的实例注入正确的实例

时间:2011-06-16 13:59:29

标签: c# dependency-injection ioc-container ninject ninject-2

我找不到合适的问题,所以我会让我的代码说出来。

我有存储库:

class Repository
{
    public Repository(DbContext ctx)
    {

    }
}

然后我有这个绑定:

Bind<IRepository>().To<Repository>();
Bind<DbContext>().To<UserStoreContext>().When...
Bind<DbContext>().To<CentralStoreContext>().When...

然后我有类需要访问db的

class Foo
{
    public Repository(IRepository userRepo, [CentralStoreAttribute]IRepository centralRepo)
    {

    }
}

我应该如何配置两个DbContext绑定,以便将具有正确上下文的存储库(基于CentralStoreAttribute)注入到Foo构造函数中?

4 个答案:

答案 0 :(得分:1)

我在概念证明中尝试了这一点,但最终走向了另一个方向。

Bind<IRepository>().ToMethod(x =>
{
  var repositoryType = x.Kernel
                .Get<IConfigObject>()
                .SomeStringPropertyDenotingTheRepository;

  switch (repositoryType )
  {
    case "1": return (IRepository)new Repository1();
    default: return (IRepository)new Repository2();
  }
}).InRequestScope();

虽然它有效,但我从未弄清楚它是否正在使用我的IObjectB单例实例或实例化一个新实例 - 应该很容易弄明白。我认为每次我在IRepository上使用DI时都会调用ToMethod - 再次未经验证。

答案 1 :(得分:1)

使用When(Func<IRequest, bool> condition)重载来递归检查,如果给定请求或其祖先之一r.Target.IsDefined(typeof(TAttribute), false)为真r.ParentRequest

答案 2 :(得分:0)

Bind<IRepository>().To<Repository>();
Bind<DbContext>().To<CentralStoreContext>()
    .When( context => context.Target != null 
        && context.Target.GetCustomAttributes( typeof( CentralStoreAttribute ) ) != null );

// make the general binding after the more specific one
Bind<DbContext>().To<UserStoreContext>();

答案 3 :(得分:0)

我不是依赖于正确位置的属性,而是创建几种实际上只是别名的类型。这很有用,因为对于Ninject(以及可能是其他IoC容器),我们要求通过类型名称来依赖它们。

因此,如果您需要能够“请求”一个用户存储库而不是一个中央存储库,我会创建类似于它的类型:

interface IRepository {  /* methods and properties */ }
interface IUserRepository : IRepository {}
interface ICentralRepository : IRepository {}

class Foo
{
   public Foo(IUserRepository userRepo, ICentralRepository centralRepo)
   {
      // assign to fields
   }
}

我更喜欢这个,因为Ninject根本不会流入我的应用程序,它更具说明性,我认为它比任何基于约定的属性方法更容易记住,就像你正在尝试的那样。