2

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())` ?

Shubhajyoti Ghosh
  • 1,292
  • 5
  • 27
  • 45
  • For 1. and 2. you should use a separate binding. You could in theory use conventions and tell it to bind all classes in the whole assembly to its default interface, but middle to long term this will cause more complexities than specifying concrete singular bindings. Please also note that you can use multiple conventional bindings! – BatteryBackupUnit Feb 28 '14 at 09:14

2 Answers2

5

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.

Maxoizs
  • 115
  • 2
  • 4
BatteryBackupUnit
  • 12,934
  • 1
  • 42
  • 68
2

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();
Daniel B
  • 4,145
  • 1
  • 21
  • 21