2

I would like to organize my Ninject bindings by separating them into Ninject modules. However, I have more than one application that would be using these modules. One of them is an ASP.Net MVC application, another is a console application, another a windows service, etc, etc. In the MVC app, I would like to use the InRequestScope scope binding, but in another application (that references my core assemblies where the Ninject modules are located) I would like to use a different scope binding. Is this possible?

As my infrastructure grows and the registration for all of my bindings becomes very large and verbose, I end up repeating these bindings in several different composition roots - the only difference between them being the lifetime scope of each binding. I'd really like to make this more DRY.

What would be ideal is the following (pseudo-code):

Core assembly which multiple apps reference

public class MyModule : NinjectModule {
    public override Load(){
        Kernel.Bind<IMyType>().To<MyType>();
    }
}

In the MVC application

kernel.Load(new MyModule())
    .Configure(p => p.UseInRequestScope);

In another application

kernel.Load(new MyModule())
    .Configure(p => p.UseInTransientScope);
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
rwisch45
  • 3,692
  • 2
  • 25
  • 36

1 Answers1

0

A composition root is for composing an application. By extension, if you have more than one application, you should have as many composition roots.

They are not meant for reuse, as this would tightly couple the applications together. As pointed out in the post:

It makes no more sense to attempt to reuse a Composition Root than it does attempting to 'reuse' an application.

So the short answer is to use a composition root per application, and then you can scope the relationships per application any way you want to. By combining composition roots of your applications, you are creating (at least) one artificial problem that wouldn't exist if you just kept them separate.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • I understand, and I've read those articles. I've also seen examples like [this](http://aaron-hoffman.blogspot.com/2014/04/ninject-set-default-to-request-scope.html?m=1). As my infrastructure grows and the registration for all of my bindings becomes very large and verbose, I end up repeating these bindings in several different composition roots - the only difference between them being the lifetime scope of each binding. Are you saying there is no way to make this more DRY? – rwisch45 Mar 12 '15 at 12:32
  • One of the advantages of using DI is the ability to create convention-based configuration. Many DI containers allow you to define your own conventions. If you factor your configuration to be convention-based, you won't have a lot of repetitive code, in fact there won't be much configuration code at all. DRY applies to a single application as pointed out in the article. It is possible to cheat by moving some code into modules and then using the linked file feature of Visual Studio to share the modules,but it means that the testing and deployment of the applications are forever coupled together. – NightOwl888 Mar 12 '15 at 13:32
  • Also, keep in mind that it is not *really* possible to [automate testing of a DI configuration](http://blog.ploeh.dk/2011/12/21/TestingContainerConfigurations/). So, altering a configuration of one application could unwittingly break the configuration of another application if the configurations are shared. Loose coupling trumps DRY in this case in terms of maintainability. – NightOwl888 Mar 12 '15 at 13:35
  • 1
    I disagree with both of NightOwl's statements.1) Although each application has its own composition root, that doesn't mean they can't share some code. Take a look at [this answer](https://stackoverflow.com/a/9505530) for instance. 2) It is possible and even advisable to automate testing of your DI configuration. This is expessed quite well [here](https://stackoverflow.com/a/28948205). – Steven Mar 12 '15 at 20:24