Reputation: 5929
Hi I am using the Ninject.MVC Nuget package with my MVC3 app and I have the current bindings setup for some constructor injection.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<ERSUnitOfWork>();
kernel.Bind<IRepository<Recipe>>().To<GenericRepository<Recipe>>();
}
My controller example is below:
public class RecipesController : Controller
{
private readonly IUnitOfWork unitOfWork;
private readonly ERSDbContext context;
private readonly IRepository<Recipe> recipeRepository;
public RecipesController(IUnitOfWork unitOfWork, IRepository<Recipe> recipeRepository)
{
this.context = new ERSDbContext();
this.unitOfWork = unitOfWork;
this.recipeRepository = recipeRepository;
}
}
I want to remove the private DBContext property from the controller and pass the new ERSDbContext() to the constructors of ERSUnitOfWork and the GenericRepository as part of the constructor injection that Ninject is performing, but preferably keep the initialising of the ERSDbContext class inside the controller?
Any help on how you do this would be appreciated. Thanks
I am kind of hoping that it doesn't require my NinjectWebCommon class having to create the DbContext, I wanted that to be initialised in the controller.
Upvotes: 2
Views: 1728
Reputation: 5929
Due to my concurrency issue, I removed the use of the factory for the time being and I am using this approach because I am short for time.
kernel.Bind<ERSDbContext>().ToSelf().InRequestScope();
Then in my UoW and GenericRepository the constructors expect a ERSDbContext type param.
I would like to improve this approach later but for now this works.
Upvotes: 0
Reputation: 74530
This is a matter of how you abstract your dependencies.
Because you want to have control over when you create your DbContext
instance, you should have a factory that will create your type-specific DbContext
instances, like so:
public interface IDbContextFactory
{
T CreateDbContext<T>() where T : DbContext;
}
(Note, if your DI framework handles type parameters on the generic interface fairly well, then you could go with the IDbContextFactory
interface that was introduced with Entity Framework 5)
If you only ever need to create typed DbContext
instances with a default, parameterless constructor, you can define your interface like so:
public interface IDbContextFactory
{
T CreateDbContext<T>() where T : DbContext, new();
}
And then define an implementation like so:
public class DbContextFactory : IDbContextFactory
{
#region Implementation of IDbContextFactory
public T CreateDbContext<T>() where T : DbContext, new()
{
// Create a new instance of T and return.
return new T();
}
#endregion
}
If you need to call a different constructor, then you'd remove the new()
constraint and have to use reflection calls (or, you can create a lambda expression and cache it based on the type of T
) to create the typed DbContext
.
From there you associate the IDbContextFactory
contract with your implementation and inject the IDbContextFactory
implementation into your class, like you would any other interface.
Upvotes: 3
Reputation: 93424
This is one of the benefits of Dependency Injection, it will automatically resolve all constructor parameters and their dependent constructor parameters. It does all this for you, just just need to define the mappings for the objects.
So in your case, you just do this:
kerel.Bind<ERSDbContext>().ToSelf();
Then you can just add ERSDbContext to your UoW and Repo and you're good.
If you want to unit test things, then you will need to abstract your context somehow, either as casperOne mentions or as I mentioned (where you make your DbContext derive from a generic interface) and then do this instead:
kernel.Bind<IDbContext>().To<ERSDbContext>();
One of the benefits of using DI is that it controls the lifetime of objects. If you defer construction of the DbContext to outside of your DI container, then you must manage its lifetime manually, instead of allowing the DI container to manage it based on a lifetime policy (such as automatically destroying it at the end of a request).
I see no measureable benefit to delaying creating the context. I think you are doing premature optimization.
Upvotes: 1