2

嗨,我正在将 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,我希望在控制器中对其进行初始化。

4

3 回答 3

3

这是您如何抽象依赖关系的问题。

因为您想控制创建DbContext实例的时间,所以您应该有一个工厂来创建特定类型的DbContext实例,如下所示:

public interface IDbContextFactory
{
     T CreateDbContext<T>() where T : DbContext;
}

(注意,如果您的 DI 框架很好地处理了泛型接口上的类型参数,那么您可以使用 Entity Framework 5 引入的IDbContextFactory接口

如果您只需要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()约束并且必须使用反射调用(或者,您可以创建一个 lambda 表达式并根据 的类型对其进行缓存T)来创建 typed DbContext

从那里您将IDbContextFactory合同与您的实现相关联并将IDbContextFactory实现注入您的类,就像您对任何其他接口一样。

于 2012-09-16T23:07:46.687 回答
1

这是依赖注入的好处之一,它会自动解析所有构造函数参数及其依赖的构造函数参数。它为您完成所有这些,只需要定义对象的映射。

所以在你的情况下,你只需这样做:

kerel.Bind<ERSDbContext>().ToSelf();

然后你可以将 ERSDbContext 添加到你的 UoW 和 Repo 中,你就很好了。

如果你想对事物进行单元测试,那么你需要以某种方式抽象你的上下文,无论是 casperOne 提到的还是我提到的(你让你的 DbContext 派生自一个通用接口),然后改为这样做:

kernel.Bind<IDbContext>().To<ERSDbContext>();

使用 DI 的好处之一是它可以控制对象的生命周期。如果将 DbContext 的构建推迟到 DI 容器之外,则必须手动管理其生命周期,而不是允许 DI 容器根据生命周期策略来管理它(例如在请求结束时自动销毁它)。

我认为延迟创建上下文没有可衡量的好处。我认为你正在做过早的优化。

于 2012-09-16T23:31:13.237 回答
0

由于我的并发问题,我暂时取消了工厂的使用,我正在使用这种方法,因为我的时间很短。

kernel.Bind<ERSDbContext>().ToSelf().InRequestScope();

然后在我的 UoW 和 GenericRepository 中,构造函数需要一个 ERSDbContext 类型参数。

我想稍后改进这种方法,但现在这可行。

于 2012-09-17T14:48:08.707 回答