How to configure Ninject so that it would inject r

2019-05-17 09:28发布

I can't find right words for my question so i will let my code speak instead.

I have Repository:

class Repository
{
    public Repository(DbContext ctx)
    {

    }
}

then i have this bindings:

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

and then i have class that needs to access both db's

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

    }
}

How should i configure two DbContext bindings so that repositories with right contexts (based on CentralStoreAttribute) would be injected into Foo constructor?

4条回答
\"骚年 ilove
2楼-- · 2019-05-17 10:14

Use the When(Func<IRequest, bool> condition) overload to check recursivly if r.Target.IsDefined(typeof(TAttribute), false) is true for the given request or one of its anchestors r.ParentRequest

查看更多
beautiful°
3楼-- · 2019-05-17 10:15

I tried this in a proof of concept but eventually went in a different direction.

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();

While it worked, I never figured out if it was using my singleton instance of IObjectB or instantiating a new instance - should be pretty easy to figure out though. I figured it was calling ToMethod every time I used DI on IRepository - again not verified.

查看更多
甜甜的少女心
4楼-- · 2019-05-17 10:26

Rather than relying on attributes in the right places, I usually create several types that are effectively just aliases. This is useful since with Ninject (and presumably other IoC containers) we're asking for dependencies by their type-name.

So if you need to be able to "request" a user repository vs a central one, I would create types that alias it like this:

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

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

I prefer this because then Ninject doesn't bleed into my app at all, it's more declarative, and I think it's simpler to remember than any convention based attribute approach like the one you're trying.

查看更多
疯言疯语
5楼-- · 2019-05-17 10:27
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>();
查看更多
登录 后发表回答