依赖注入,实体框架

时间:2015-08-10 13:42:10

标签: c# entity-framework dependency-injection

所以我使用实体框架并尝试重构我的代码以使用依赖注入。在我到达DbContext之前,一切都很顺利。这是一个Windows窗体应用程序。到目前为止,我有这个:

 public interface ICruiserContext
{
    DbSet<Customer> Customers { get; set; }
    DbSet<Address> Addresses { get; set; }
    DbSet<Order> Orders { get; set; }
    DbSet<Item> Items { get; set; }
    DbSet<SkuMap> SkuMaps { get; set; }
    DbSet<UnitOfMeasure> UnitOfMeasures { get; set; }
    DbSet<RelativeUnit> RelativeUnits { get; set; }
    DbSet<ShippingMethod> ShippingMethods { get; set; }
    DbSet<ShippingMethodMap> ShippingMethodMaps { get; set; }
}

我有一个需要Context的控制器(大多数代码被删除):

   class ShippingMethodMapper : IMapper
{
    private readonly string _shippingMethod;
    private readonly ICruiserContext _context;

    public ShippingMethodMapper(string shippingMethod,  ICruiserContext context)
    {
        _shippingMethod = shippingMethod;
        _context = context;
    }

    public ICollection<string> GetRemoteValues()
    {
        return new List<string>
        {
            _shippingMethod
        };
    }

    public ICollection<string> GetLocalValues()
    {
        throw new NotImplementedException();
    }

     public void Save(string remoteValue, string localValue)
    {
        throw new NotImplementedException();
    }
}

因此,由于您只想对一个事务使用上下文,因此每次创建此控制器时,都需要创建一个新的上下文,但如果我只是使用

注入
context = new CruiserContext();

然后创建控制器的代码不再可测试,因为它现在具有对数据库上下文的硬依赖性,并且如果上下文发生了变化,我将不得不编辑创建新实例的每个文件,违反Open /封闭原则。所以我的想法可能是使用一个简单的工厂,并委托它的实例化责任:

public static class ContextService
{
    public static ICruiserContext GetContext()
    {
        return new CruiserContext();
    }
}

但是由于静态类不能有接口,现在我只对工厂有了很强的依赖性。那么注入可以测试和模拟的dbContext的最佳方法是什么。

2 个答案:

答案 0 :(得分:3)

使用带接口

的非静态类
public interface ICruiserContextFactory
{
    ICruiserContext CreateContext();
}

当您使用IDisposable实例时,这是一个标准的方法 将工厂接口传递给您的类也可以编写单元测试。

答案 1 :(得分:2)

您正确使用控制反转原理。 Nex步骤 - 使用IoC-Containers。它强大的模式将帮助您解决注射和测试中的问题。