17

I have a MVC 3 solution configured with Ninject using a repository pattern. Some of my bindings include:

kernel.Bind<IDatabaseFactory>().To<DatabaseFactory>().InRequestScope();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<IMyRepository>().To<MyRepository>().InRequestScope();
kernel.Bind<IMyService>().To<MyService>().InRequestScope();
kernel.Bind<ILogging>().To<Logging>().InSingletonScope();

I also added a console application to my solution and I want to leverage the same repository and services. My Ninject configuration for the console application looks like:

kernel.Bind<IDatabaseFactory>().To<DatabaseFactory>().InSingletonScope();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InSingletonScope();
kernel.Bind<IMyRepository>().To<MyRepository>().InSingletonScope();
kernel.Bind<IMyService>().To<MyService>().InSingletonScope();
kernel.Bind<ILogging>().To<Logging>().InSingletonScope();

My console code looks like:

static void Main(string[] args)
{
    IKernel kernel = new StandardKernel(new IoCMapper());

    var service = kernel.Get<IMyService>();
    var logger = kernel.Get<ILogging>();

    ... do some processing here
}

This works just fine but I want t be sure that I am configuring Ninject correctly for a console application. Is it correct to use InSingletonScope() for all my bindings in my console application? Should I be configuring it differently?

Thomas
  • 5,888
  • 7
  • 44
  • 83

1 Answers1

12

Do you want one and only one instance of each of your repository services for the whole application? If so, then use InSingletonScope.

Is your console application multithreaded? If this is the case and you want a new instance of your services for each thread then you will use InThreadScope.

If you want a new instance of the service(s) each time they are called for, set it to InTransientScope.

You also have the option of defining your own scope using InScope. Bob Cravens gives a good overview of each of these here http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/

Scott Lance
  • 2,239
  • 1
  • 18
  • 19
  • The console application has a simple for loop that iterates through a few urls, scrapes the content, processes it and passes it to the services to save it to the database. No async requests so I assume this will make it single threaded? Which approach fits this scenario best? – Thomas Jul 08 '11 at 17:36
  • If you want to use the same database connection each time then you can use InSingletonScope or InRequestScope. For a synchronous operation that should be fine. If for any reason your requests to the database service becomes asynchronous (which is common in UoW scenarios) then you may start running into problems with the database connection being used by two different calls at the same time. This happened to me several months ago and I spend days trying to figure out what was going on – Scott Lance Jul 08 '11 at 17:39
  • When you say "your requests to the database service becomes asynchronous" I am assuming I actually have to modify my code to "become asynchronous" or is this something that can occur "under the hood"? – Thomas Jul 08 '11 at 19:00
  • Correct, if you change it later and forget about the scope your services are in you may start seeing random errors – Scott Lance Jul 08 '11 at 19:29
  • 1
    Bear in mind that Ninject will dispose objects implementing the IDisposable interface as long as they are not bound `InTransientScope` or are missing an `InXyzScope` call (which is the same thing). – Umar Farooq Khawaja Aug 22 '15 at 09:37
  • @ScottLance I am having the same scenario with one twist , I am calling a method in service layer which calls "TryValidateObject" method of System.ComponentModel.DataAnnotations.Validator class. Now the Model passed to this method has few custom validators attached to it and the Custom validator has dependency on service which is injected through property with [Inject] attribute. In this validation attribute the service is not getting injected in console app . The service gets injected properly when in Web App but in console app its not getting injected. Any ideas how to make it work. – Vipresh Oct 27 '16 at 17:04
  • @Vipresh If I'm understanding correctly, you are trying to inject your validator into another validator in a console app and it's not working? Console apps work quite a bit differently than MVC or WebForm apps in Ninject. I believe the problem here (with knowing nothing about your code) is that Console app doesn't have a way to bootstrap Ninject to inject into other classes, where as bootstrapping is setup as part of your web app startup. You will probably want to look into a service locator pattern for a console app, do a search on google and there are plenty of examples – Scott Lance Oct 27 '16 at 20:35
  • @ScottLance , No I am not trying to inject validator into another validator, I am trying to inject a Service dependency in my Class derived from "ValidationAttribute" attribute. I have been able to do this successfully in an Web App using the "[Inject]" attribute and making my dependency public property. And yes as U suggested the entry point Class in My Console App is fetched using Service Locator, this also works fine the class has all the dependency injected into it. But the problem starts when I am creating a model and trying to validate it. The model class has validation attirbutes – Vipresh Oct 30 '16 at 12:04
  • The model class in console app is created by my method as opposed to "ModelBinder" in an WebApp. If my Model class is created by model binders all the Validation Attirbutes in it have their dependency injected in them and I check the ModelState in controller action. But the Model class created manually by me has no dependency injected in its validation attribute ofcourse because its created by my code. So what I want is an way of passing My model class to NInject after creating it or vice versa so I can validate it using principle of DRY. – Vipresh Oct 30 '16 at 12:15