LeoQns
LeoQns

Reputation: 1322

How to bind using Ninject Conventions Extension?

I like to bind bellow code with Ninject auto binding. Is it possible to use both mannual & auto binding within a single project? Let;s take bellow manual binding, I want to achieve with auto binding. Please tell me how to achieve this.

  1. kernel.Bind<TestContext>().ToSelf().InRequestScope();

  2. kernel.Bind<IUnitOfWork<TestContext>>().To<UnitOfWork<TestContext>>();

Bellow all interface inherited from base Interface : IRepository< Model >

3 . kernel.Bind<IUserRepository>().To<UserRepository>();

4 . kernel.Bind<IAccountRepository>().To<AccountRepository>();

5 . kernel.Bind<IMessageRepository>().To<MessageRepository>().WithConstructorArgument("apikey", AppSettingsManager.GetSmsApiKey)

Additional

Do I need to write .Exclude<MessageRepository>() for multiple classes If I required to do it such as

.Exclude<ARepository>() .Exclude<BRepository>() .Exclude<CRepository>() ?

and for 1 & 2 is required separate manual binding ? or 1 can be done using BindToSelf()' and.Configure(b => b.InRequestScope())` ?

Upvotes: 2

Views: 5583

Answers (2)

Daniel B
Daniel B

Reputation: 4545

The previous solution works if you have only few number of exceptions. If there are more of them you will end up with a lot of conventions which doesn't make sense.

Use IBindingRoot.Rebind method to override bindings that overlap with the one already covered by the convention.

IBindingRoot.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.BindAllInterface());

IBindingRoot.Rebind<IMessageRepository>().To<MessageRepository>)
.WithConstructorArgument("apikey", AppSettingsManager.GetSmsApiKey)
.InRequestScope();

Upvotes: 2

BatteryBackupUnit
BatteryBackupUnit

Reputation: 13233

Yes, it is possible to use convention binding and single binding in the same project, even in the same module.

IBindingRoot.Bind(x => x
    .FromThisAssembly()
    .IncludingNonePublicTypes()
    .SelectAllClasses()
    .InheritedFrom(typeof(IRepository<>))
    .BindDefaultInterface()
    .Configure(y => y.InRequestScope()));

However you won't be able to pass a constructor argument to a specific class. So i suggest replacing the constructor argument with an interface which wraps the access to the configuration (that's a nice design anyway).

Alternatively you can also do this:

IBindingRoot.Bind(x => x
    .FromThisAssembly()
    .IncludingNonePublicTypes()
    .SelectAllClasses()
    .InheritedFrom(typeof(IRepository<>))
    .Exclude<MessageRepository>()
    .BindDefaultInterface()
    .Configure(y => y.InRequestScope()));

IBindingRoot.Bind<IMessageRepository>().To<MessageRepository>)
    .WithConstructorArgument("apikey", AppSettingsManager.GetSmsApiKey)
    .InRequestScope();

--> You can do one .Exclude<TRepository>() for every repository, where the convention binding is not sufficient. For every exlucded binding you will have to specifiy one yourself. As above: conditional binding for all classes implementing IRepository<> except class MessageRepository, which gets its own binding.

Also have a look at this: https://github.com/ninject/ninject.extensions.conventions/wiki/Projecting-Services-to-Bind

Addendum: Note that you can specify multiple conventional bindings, for example:

IBindingRoot.Bind(x => x
    .FromThisAssembly()
    .SelectAllClasses()
    .InheritedFrom(typeof(IFoo))
    .BindDefaultInterface()
    .Configure(y => y.InRequestScope()));


IBindingRoot.Bind(x => x
    .FromThisAssembly()
    .SelectAllClasses()
    .InheritedFrom(typeof(IBar))
    .BindToSelf()
    .Configure(y => y.InRequestScope()));

Is totally ok.

Upvotes: 5

Related Questions