您好我正在使用Ninject.MVC Nuget包和我的MVC3应用程序,并且我有一些构造函数注入的当前绑定设置。
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<ERSUnitOfWork>();
kernel.Bind<IRepository<Recipe>>().To<GenericRepository<Recipe>>();
}
我的控制器示例如下:
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;
}
}
我想从控制器中删除私有DBContext属性,并将新的ERSDbContext()传递给ERSUnitOfWork和GenericRepository的构造函数,作为Ninject正在执行的构造函数注入的一部分,但最好保持ERSDbContext类的初始化控制器?
任何有关如何执行此操作的帮助将不胜感激。感谢
我有点希望它不需要我的NinjectWebCommon类必须创建DbContext,我希望它在控制器中初始化。
答案 0 :(得分:3)
这是你如何抽象依赖关系的问题。
因为您希望控制何时创建DbContext
实例,所以您应该有一个工厂来创建特定于类型的DbContext
实例,如下所示:
public interface IDbContextFactory
{
T CreateDbContext<T>() where T : DbContext;
}
(注意,如果您的DI框架很好地处理通用接口上的类型参数,那么您可以使用Entity Framework 5中引入的IDbContextFactory
interface)
如果您只需要使用默认的无参数构造函数创建类型化DbContext
实例,则可以像这样定义您的界面:
public interface IDbContextFactory
{
T CreateDbContext<T>() where T : DbContext, new();
}
然后定义一个类似的实现:
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
}
如果你需要调用另一个构造函数,那么你要删除new()
constraint并且必须使用反射调用(或者,你可以创建一个lambda表达式并根据{{的类型来缓存它) 1}})创建键入的T
。
从那里,您将DbContext
合同与您的实施相关联,并将IDbContextFactory
实施注入您的班级,就像您使用任何其他界面一样。
答案 1 :(得分:1)
这是依赖注入的一个好处,它将自动解析所有构造函数参数及其相关的构造函数参数。它为您完成所有这些,只需要定义对象的映射。
所以在你的情况下,你只需这样做:
kerel.Bind<ERSDbContext>().ToSelf();
然后你就可以在你的UoW和Repo上添加ERSDbContext了,你很好。
如果你想对单元测试进行单元测试,那么你需要以某种方式抽象你的上下文,或者像casperOne所提到的那样,或者正如我所提到的那样(你将DbContext从一个通用接口派生出来)然后这样做:
kernel.Bind<IDbContext>().To<ERSDbContext>();
使用DI的一个好处是它可以控制对象的生命周期。如果将DbContext的构造推迟到DI容器之外,则必须手动管理其生命周期,而不是允许DI容器根据生命周期策略(例如在请求结束时自动销毁它)来管理它。
我认为延迟创建上下文没有任何可衡量的好处。我认为你正在做过早的优化。
答案 2 :(得分:0)
由于我的并发问题,我暂时取消了工厂的使用,我正在使用这种方法,因为我的时间很短。
kernel.Bind<ERSDbContext>().ToSelf().InRequestScope();
然后在我的UoW和GenericRepository中,构造函数需要一个ERSDbContext类型的参数。
我想稍后改进这种方法,但现在可行。