I used Ninject specifically in the MVC application. How you do this with Ninject depends on the configuration or binding of your dependencies. When you do this, you indicate how you want to manage the life cycle of your object. In most cases, web applications will have objects for each request, as you indicated in your question.
In your question, I noticed that your DomainContext is created by an IDomainService object and used by other objects. If the domain service object is a kind of factory for DomainContext, then you do not have a big problem - this becomes an exercise in how you configure Ninject to provide specific objects and dependency attachments.
Here are general guidelines on how you structure your application β keep in mind that I donβt have a complete understanding of your interfaces and classes:
public class GlobalApplication : NinjectHttpApplication { protected override void RegisterRoutes(RouteCollection routes) { // Your normal route registration goes here ... routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = "" } ); } // This function is resposible for creating a Ninject kernel. This is where // the magic starts to happen. protected override IKernel CreateKernel() { var modules = new IModule[] { new AutoWiringModule(), new AutoControllerModule( Assembly.GetExecutingAssembly()), new ServiceModule() }; return new StandardKernel(modules); } }
Note that the easiest way to get Ninject to work is to derive the application class from the NinjectHttpApplication class. You will need to change the RegisterRoutes register to an override method, and you will also need to implement the CreateKernel method. The CreateKernel method is responsible for returning the Ninject kernel, which itself is an IoC container.
In the CreateKernel method, the Ninject-provided AutoControllerModule module checks the assemblies for the MVC controller classes and registers them with the container. This means that dependency on these controllers can now be introduced by Ninject, as it has become the controller supplier for the application. The ServiceModule class is the one you need to create to register all your services with Ninject. I assume it will look something like this:
internal class ServiceModule : StandardModule { public override void Load() { Bind<IDomainService>() .To<MyDomainService>() .Using<OnePerRequestBehavior>(); Bind<DomainContext>() .ToMethod( ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext ) .Using<OnePerRequestBehavior>(); Bind<IService>() .To<MyServiceType>() .Using<OnePerRequestBehavior>(); } }
Ninject got a pretty expressive free interface for configuration. Note that each statement basically associates a particular class with the interface that it implements. The phrase βUseβ in the statement tells the Ninject core that the object will live only for the life of the request. So, for example, this means that at any time when an IDomainService is requested from the Ninject kernel during the same request, the same object is returned.
As for the context objects, I take the hit that your domain service creates these contexts and acts like a factory sort. In this regard, I have linked the instances of the DomainContext classes above, which will be created by getting the value of the a property called CurrentDomainContext from the IDomainService object. This is what the lambda above does. The good thing about the "ToMethod" binding in Ninject is that you have access to the Ninject activation context object, which allows you to resolve objects using the kernel. This is exactly what we do to get the current domain context.
The following steps are designed to properly match your objects to dependencies. For example, you say that ITrainingService is used only in the TrainingController class. Thus, in this case, I guarantee that the TrainingController has a constructor that accepts the ITrainingService parameter. In this constructor, you can save the reference to ITrainingService in a member variable. How in:
public class TrainingController : Controller { private readonly ITrainingService trainingService; public TrainingController(ITrainingService trainingService) { this.trainingService = trainingService; }
Remember that Ninject has already registered all of your controllers with the Ninject core, so when this controller is created and its action is called, you will have a link to the ITrainingService using the trainingService member variable.
Hope this helps you. Using IoC containers can be confusing from time to time. Note that I highly recommend that you check out the Ninject documentation - this is a very well-written introduction to the concepts of Ninject, as well as the concepts of DI / IoC. I also declined to discuss the AutoWiringModule shown above; However, Nate Kochari (creator of Ninject) has a good blog post about this feature.
Good luck