我无法理解如何正确设计我的域对象。我一直在努力解决的问题是如何用数据填充我的域对象。我发现的例子对于真正帮助我来说是微不足道的。我尝试了各种各样的方法,但我不喜欢它们中的任何一种。假设您需要将大量数据传递到类中,以便将其捆绑在POCO中。
我的第一个方向(将数据传递给构造函数):
public class MyClass
{
private readonly ICalculator _calculator;
private readonly MyClassDataPOCO _data;
public MyClass(ICalculator _calculator, MyClassDataPOCO data)
{
this._calculator = _calculator;
_data = data
这不好用,因为那时你的IOC容器不能自动初始化你的类。
第二个方向(将数据传递到操作中):
public class MyClass
{
private readonly ICalculator _calculator;
public MyClass(ICalculator _calculator)
{
this._calculator = _calculator;
}
public decimal CalculateComplicatedValue1(MyClassDataPOCO data)
{
}
public decimal CalculateComplicatedValue2(MyClassDataPOCO data)
{
}
我出于各种原因不喜欢这个
第三方向(仅允许您通过静态工厂方法创建课程):
public class MyClass
{
private readonly ICalculator _calculator;
private MyClassDataPOCO _data;
private MyClass(ICalculator _calculator)
{
this._calculator = _calculator;
}
public static MyClass Create(MyClassDataPOCO data)
{
return Create(_container.GetInstance<ICalculator>(), data);
}
public static MyClass Create(ICalculator calculator, MyClassDataPOCO data)
{
//do some input validation here
var myReturn = new MyClass(calculator);
myReturn._data = data;
return myReturn;
}
我猜我最喜欢这个选项中的所有选项。我唯一不喜欢的是必须有两个创建函数,所以它可以进行单元测试(所以我可以注入ICalculator)。
我没有尝试的唯一选择是属性注入,因为id不认为通过属性注入数据是个好主意。
答案 0 :(得分:2)
您根据业务概念和用例设计域对象(DO)。根据我的经验,这意味着你的物体应该非常纤细。 DO基于概念定义实现。业务用例在服务中实现(可以是应用服务,可以是域服务,它取决于上下文),它将使用DO来更新内容。
当我设计一个对象时,我只想到我需要什么样的行为。所有对象都应该具有初始状态,因此您使用初始值传递DTO(一切都是POCO,我们不关心这里的持久性)。实际上,每种方法都是一样的。
关于持久性,因为我使用CQRS,我只关心保存/获取对象。我个人更喜欢json这个对象(如果我不使用事件源)所以save = serialize,get = deserialize。关于封装,您可以将json序列化程序配置为使用私有属性,并且基本上具有私有属性是您唯一的妥协。
正如我之前所说的,用例是作为服务实现的,因此在您的方案中,MyClass
实际上是服务,而不是DO。作为拇指规则,DO包含仅数据和行为,这有助于定义对象。 CalculateComplicatedValue
看起来不像概念的一部分,但它看起来像一个用例,因此就是一种服务。
您在这里不需要工厂,实例化DO通常很简单,但是服务通常由DI容器实例化,因为在大多数情况下服务确实使用其他服务(如存储库或验证器)