【发布时间】:2014-10-30 08:24:45
【问题描述】:
我有许多将 WPF 与 MVVM 结合使用的系统。对于单元测试,我们将依赖项注入到视图模型中,但是我发现在构建时注入依赖类时,我们无法控制依赖对象的生命周期,例如实体框架 DbContext。
一个简单的场景如下:
public class FooVM
{
private readonly IBarService _barService;
// Set in the UI via Databinding
public string Name { get; set; }
public string OtherName { get; set; }
public FooVM(IBarService barService)
{
_barService = barService;
}
public void SaveFoo()
{
_barService.SaveFoo(Name);
}
public void SaveBar()
{
_barService.SaveBar(OtherName);
}
}
public class BarService : IBarService
{
private readonly IEntityContext _entityContext;
public BarService(IEntityContext entityContext)
{
_entityContext = entityContext;
}
public void SaveFoo(string name)
{
// some EF stuff here
_entityContext.SaveChanges();
}
public void SaveBar(string otherName)
{
// some EF stuff here
_entityContext.SaveChanges();
}
}
VM 需要使用该服务,因此已将其注入,该服务需要 IEntityContext,因此已注入该服务。问题出现在我们调用SaveFoo 和SaveBar 的VM 中,因为_entityContext 对象在一次调用后是脏的。理想情况下,我们希望在每次调用后处理 _entityContext 对象。
我找到的唯一方法是使用依赖注入来注入容器,然后调用代码如下:
public class FooVM
{
private readonly IInjector _injector;
// Set in the UI via Databinding
public string Name { get; set; }
public string OtherName { get; set; }
public FooVM(IInjector injector)
{
_injector = injector;
}
public void SaveFoo()
{
var barService = _injector.GetUniqueInstance<IBarService>();
barService.SaveFoo(Name);
}
public void SaveBar()
{
var barService = _injector.GetUniqueInstance<IBarService>();
barService.SaveBar(OtherName);
}
}
通过这种方式,容器 (IInjector) 就像一个服务定位器,效果很好,除了对于单元测试来说很笨重。有没有更好的方法来管理这个?我知道这样做几乎会使依赖注入的所有好处无效,但我想不出另一种方法。
编辑:进一步的例子
假设您有一个带有两个按钮的窗口。一项服务位于其后面,该服务已通过依赖注入注入。您单击按钮 A 并加载一个对象,对其进行修改并保存,但是这会失败(由于某种原因,假设 DbContext 中的某些验证失败),您会显示一条很好的消息。
现在您单击按钮 2。它加载了一个不同的对象并对其进行了修改并尝试保存,现在因为第一个按钮被按下,并且服务是相同的服务,具有相同的上下文,此操作将失败原因与单击按钮 A 时一样。
【问题讨论】:
标签: c# entity-framework mvvm dependency-injection service-locator