作为一个例子,假设我有一个像这样的Person BO:
class Person
{
private int age;
public bool isBigEnough => age > 10;
}
我希望age
成为Person
的内部状态,但我仍然需要将我的BO传达给某个api。或者在我的班级中有私人领域,我想发送到某个地方已经意味着它应该是公开的?
___更新:
除了@Alexey Groshev提到的方法之外,我还遇到了另一种方法:我们将BO类的数据分成一些带有公共访问器的Data类。 BO用它的api(可能使用组合)包装这些数据,并且在需要时它可以将其状态作为Data类返回为clone。因此,dto转换器将能够访问Domain对象的状态,但无法修改它(因为它只是一个副本)。
答案 0 :(得分:1)
有多种选择,但很难推荐任何内容,因为我不了解您的项目/产品的详细信息。无论如何,我只列举一些。
您可以使用AutoMapper将BO映射到DTO,反之亦然。我个人不喜欢这种方法,因为在中型/大型项目中控制它是非常困难的(但可能的)。人们通常不愿意正确配置映射,只是暴露其对象的内部状态。例如,您的isBigEnough
将消失,age
将变为public
。另一个潜在的风险是人们可以将DTO映射到EF / Hibernate对象/从EF / Hibernate对象映射。你可以找到一些文章解释为什么它被认为是bad practice。
如你所知,BO可以自己创建DTO,但是你如何实现这种方法呢?您可以向实体添加方法或工厂方法,例如public PersonDto ToDto()
。或者您可以添加一个界面,例如public interface IDtoConvertable<T> { T ToDto(); }
,并选择实现它的实体或聚合根。您的Person
课程将如下class Person : IDtoConvertable<PersonDto> {... public PersonDto ToDto() {...} }
。在这两种情况下,DTO命名空间/程序集必须可由实体访问,这有时可能是一个问题,但通常它不是一个大问题。 (确保DTO无法访问更糟糕的实体。)
( C#)另一种选择是返回创建DTO的委托。我决定将它与(2)分开,因为实体本身并没有真正创建DTO,而是暴露了创建DTO的功能。所以,你可能会有这样的事情public Func<PersonDto> ToDto() {...}
。您可能希望拥有(2)中的界面,但是您明白了,不是吗?我喜欢这种方法吗?不,因为它使代码不可读。
如您所见,问题多于答案。我建议你做一些实验,检查一下对你(你的项目)有什么作用,以及什么不适合。
答案 1 :(得分:0)
我认为问题5的答案也将解决其他问题。
对于如何将DTO与业务类一起用于封装数据,是否有任何一般性考虑因素?
请记住,DTO仅用于传输数据。不要担心在DTO中实施任何类型的规则。它用于将数据从一个子系统移动到另一个子系统(不在同一子系统的类之间)。如何在目标系统中使用这些数据是你无法控制的 - 虽然作为上帝程序员你本身就知道它将如何被使用,但是不要让这些知识影响你的设计 - 因此不应该表达任何假设作为行为或知识访问者 - 所以,没有isBigEnough
。