C#Dto构造函数和依赖注入

And*_*dre 11 c# design-patterns dependency-injection

我想知道设计DTO对象构造函数的最佳实践是什么.

说我有这样的Dto对象:

class CustomerDto
{
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Phone { get; set; }
    ...
}
Run Code Online (Sandbox Code Playgroud)

有几种方法可以构造对象:

我可以声明一个构造函数:

public CustomerDto(string name, string surname, string phone, ...)
{
    this.Name = name;
    this.Surname = surname;
    this.Phone = phone;
    ...
}
Run Code Online (Sandbox Code Playgroud)

当您看到此构造函数并立即结束SRP(单一责任)违规时?

尽管这些属性都是相关的.

人们也可以说没有必要验证属性,因为这是一个DTO并且没有行为,而且行为应该放在这个映射的域对象上.

在C#中,我们还可以更优雅地构造此对象:

var dto = new CustomerDto ()
{
    Name = "Some name",
    Surname = "Some surname"
}
Run Code Online (Sandbox Code Playgroud)

或者使用流畅的构建器或NBuilder等框架.

还有自动映射框架的使用,如Automapper.问题还在于使用Ioc容器,ctor变得复杂,以及交换参数的风险,例如,你传递姓氏在哪里,反之亦然,验证可能会错过这个更容易然后如上所述的显式映射.

请帮助说服我哪种方式更好.

Rem*_*oor 12

示例中的值类型不是依赖项.依赖项为消费者提供功能(或配置).在您的情况下,它们只是分配给DTO的正常值.只要数据属于一起,即使在构造函数中分配了大量值,也不会违反SRP.在这种情况下,唯一的责任是保存数据.

此外,DTO不应由IoC容器创建,也不应具有真正的依赖关系.您应该通过持久性框架或使用自动映射手动创建它们.

如果使用构造函数或属性分配值更好取决于用法.如果需要它们,构造函数变体更好.如果它们是可选的,物业方式更好.


sll*_*sll 5

我建议使用不可变数据结构,这样DTO实体就不会暴露任何setter,显然这样构造函数应该提供初始化给定DTO的所有底层属性的能力.

所以我更喜欢:

public CustomerDto(string name, string surname, string phone, ...) 
Run Code Online (Sandbox Code Playgroud)

DTO是一个数据传输对象,尤其用于表示要在系统(分布式)边界上传递的一组属性,因此不要过多关注SRP违规.这就像Facade设计模式,它取消了一组操作/服务以简化使用.所以在这个kase Keep It Simple中赢了.

  • 我想知道的是马丁·福勒(Martin Fowler)将数据传输对象描述为持有状态且无行为的对象,实际上将其描述为减少方法调用的一种方式。通过引入构造函数参数并对其进行验证,您可以添加行为。请记住,这样做的目的是从域映射到视图,并且验证很可能发生在域对象上。那么,dto是否真的需要担心参数以及所需的条件,因为它只是在其他地方携带数据,而验证又是另一个问题? (2认同)