.net 如何在域模型实体类中注入辅助依赖项
因此,我正在努力将我的桌面/WPF解决方案从使用服务定位器模式转换为使用依赖注入。到目前为止,它相对来说比较轻松(因为在这两种情况下都使用相同的UnityContainer):我只需删除对全局/静态ServiceLocator的每个调用,并将依赖项放入构造函数中。但当涉及到存在于我的一个实体类中的助手服务时,我感到很困惑 目前我有这样的想法: 单例帮助器服务,不包含任何状态,只包含一些常用逻辑:.net 如何在域模型实体类中注入辅助依赖项,.net,entity-framework,dependency-injection,service-locator,domain-model,.net,Entity Framework,Dependency Injection,Service Locator,Domain Model,因此,我正在努力将我的桌面/WPF解决方案从使用服务定位器模式转换为使用依赖注入。到目前为止,它相对来说比较轻松(因为在这两种情况下都使用相同的UnityContainer):我只需删除对全局/静态ServiceLocator的每个调用,并将依赖项放入构造函数中。但当涉及到存在于我的一个实体类中的助手服务时,我感到很困惑 目前我有这样的想法: 单例帮助器服务,不包含任何状态,只包含一些常用逻辑: interface ICalculationsHelper { double DoCompletel
interface ICalculationsHelper { double DoCompletelyCrazyCalculations(); }
然后,在域模型实体中使用它:
class CrazyNumber
{
public int Id { get; set; }
public string Name { get; set; }
public double TheNumber { get; set; }
ICalculationsHelper _helper = ServiceLocator.Resolve<ICalculationsHelper>();
public CrazyNumber()
{
CreateCrazyNumber();
}
private void CreateCrazyNumber()
{
TheNumber = _helper.DoCompletelyCrazyCalculations();
}
}
1) EF如何为每个实体注入一个新的助手?
2) 假设我的应用程序在100个位置以各种不同的方式操纵实体——所有操作都使用默认构造函数。现在,我突然不得不修改这些算法中的每一个,以手动将iCalculationHelper传递到实体中。这是主要的混乱,使每种算法复杂化。在后台无声地加载这个“次要”服务似乎要干净得多(根据服务定位器模式)。
3) 如果在这种情况下使用服务定位器更好,那么这个域类应该如何进行单元测试(模拟服务)
谢谢
1) EF如何为每个实体注入一个新的助手
不可能为此使用IoC容器。IoC容器知道如何将依赖项注入到它自己创建的(根)对象中,而不是以其他方式创建的对象中。因此,如果您希望实体具有此依赖关系(这是有争议的,请参阅下文),您可以订阅包装的ObjectContext
事件的处理程序:
在处理程序中,您可以检查CrazyNumber
是否已具体化,并为其分配iCalculationHelper
。所以这不是构造函数注入,而是属性注入(某种程度上,不是通过IoC容器)。根据下面的备注,您还可以在那里生成其编号
,而无需注入服务
2) …使用此(…)服务定位器模式似乎更干净
我同意。如果国际奥委会因任何原因不能工作,SL是第二好的
3) 这个域类应该如何进行单元测试
这是国际奥委会的一个普遍问题。对于单元测试,如果服务本身具有无法在单元测试上下文中实现的依赖项,那么IoC容器应该能够注入模拟服务
但我怀疑您是否应该将此服务注入实体中。这涉及到一个广泛的主题,但我在这里想一想:
- 我尤其不喜欢服务在构造函数中完成其工作这一事实。对象是由EF构造的,因此无论服务做什么,它都可能干扰EF的对象构造
- 为什么要
创建其CrazyNumber
属性本身(假设您的代码只是实际案例的替身)?从面向对象的角度来看,如果它将数据和行为结合在一起,这应该会发生。换句话说,ifNumber
包含生成数字所需的状态。但在构造函数中,这种状态永远不能保证是完整的或稳定的。(它在对象物化之后)。如果不需要这种状态,那么行为就不应该存在(单一责任)CrazyNumber
- 可能您的示例有点做作,可能以后需要该服务来创建号码,例如首次访问时。同样,
也不应该有这种依赖关系,因为可能存在从未生成数字的代码路径。在这种情况下,服务是一个松散的依赖项,很难判断它何时真正需要它。在真正需要时,最好通过方法注入来“注入”:CrazyNumber
public void CreateCrazyNumber(ICalculationsHelper helper) { TheNumber = helper.DoCompletelyCrazyCalculations(); }
Math
本身一样。静态类+状态,这很糟糕。不是没有副作用的静态函数。谢谢——知道仅用于逻辑的静态类是可以的,这让我松了一口气。要跳过的篮圈太少了。
((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized +=
ObjectContext_ObjectMaterialized;
public void CreateCrazyNumber(ICalculationsHelper helper)
{
TheNumber = helper.DoCompletelyCrazyCalculations();
}