C# DDD-域如何接收客户端数据

C# DDD-域如何接收客户端数据,c#,design-patterns,domain-driven-design,C#,Design Patterns,Domain Driven Design,我计划重构一个正在维护的遗留.NET项目,主要涉及4个项目: My.Company.Web-表示层。NETMVC My.Company.Service-服务层,定义服务接口并包含命令处理程序。由web层调用 My.Company.DTO-包含用于域和web层之间数据传输的DTO类的程序集 My.Company.Domain-域层 My.Company.Data-持久层 当用户提交表单以更新某人的详细信息时,该过程看起来有点像: 控制器使用提交的数据构造一个PersondetailsTo,该对

我计划重构一个正在维护的遗留.NET项目,主要涉及4个项目:

  • My.Company.Web
    -表示层。NETMVC
  • My.Company.Service
    -服务层,定义服务接口并包含命令处理程序。由web层调用
  • My.Company.DTO
    -包含用于域和web层之间数据传输的DTO类的程序集
  • My.Company.Domain
    -域层
  • My.Company.Data
    -持久层
当用户提交表单以更新某人的详细信息时,该过程看起来有点像:

  • 控制器使用提交的数据构造一个
    PersondetailsTo
    ,该对象由多个简单字段组成,用于保存
    FirstName
    LastName
    Age
    等,以及一个名为
    addressedTo
    的复杂类型对象,该对象保存地址详细信息:
    var dto=new PersonDetails(…)
  • 控制器使用DTO调用服务层:

    _personService.UpdateDetails(dto);
    
  • 在职期间:

    public void UpdatePerson(PersonDetailsDTO dto)
    {
        var person = _personRepository.GetById(dto.PersonId);
        person.Update(dto);
        _personRepository.Update(person);
    }
    
  • 在个人域中:

    public class Person : AggregateRoot
    {
        private string FirstName;
        .... // other fields
        private Address Address;
    
        public void Update(PersonDetailsDTO dto)
        {
            FirstName = dto.FirstName;
            .... // other fields
            Address.Update(dto.AddressDTO); // update the value object - address
        }
    }
    
  • 正如您在这里看到的,
    Person
    域引用了
    PersonDetailsDTO
    。我觉得这是不对的,因为DTO是将域中的数据呈现给其客户机的手段,而不公开域本身。域应该而不是关注它如何呈现给客户

    此外,在我看来,DTO应该存在于
    My.Company.Service
    项目中,因为它是定义操作/数据传输合同的服务

    但是,服务如何将详细信息传递给域呢?它必须是一个冗长的参数列表:
    person.Update(名字、姓氏、年龄、性别、街道1、街道2、州、邮政编码……
    )。这在我看来肯定是错的

    或者域必须定义另一组自己的“DTO”来接收客户端数据吗

    我已经阅读了很多教程和帖子,似乎没有人分享我的担忧,所以我开始觉得我在这里遗漏了一些东西,有人能给我指出正确的方向吗?

    你可以这样做。 您已经有一个名为
    Address
    的值对象,类似地,您可以有另一个名为
    PersonalDetails
    的值对象,该值对象将包含名字、姓氏、年龄、性别等。
    Person
    实体将有两种行为,如
    updatePersonalDetails()
    updateAddress()
    。您的应用程序服务如下所示

    public void UpdatePerson(PersonDetailsDTO dto)
    {
        var person = _personRepository.GetById(dto.PersonId);
        Address address = new Address(dto.getStreet1, dto.getStreet2,...);
        PersonalDetails details = new PersonalDetails(dto.getFirstName,dto.getLastName(),...);
        person.updatePersonalDetails(details);
        person.updateAddress(address);
       _personRepository.save(person);
    }
    
    你可以这样做。 您已经有一个名为
    Address
    的值对象,类似地,您可以有另一个名为
    PersonalDetails
    的值对象,该值对象将包含名字、姓氏、年龄、性别等。
    Person
    实体将有两种行为,如
    updatePersonalDetails()
    updateAddress()
    。您的应用程序服务如下所示

    public void UpdatePerson(PersonDetailsDTO dto)
    {
        var person = _personRepository.GetById(dto.PersonId);
        Address address = new Address(dto.getStreet1, dto.getStreet2,...);
        PersonalDetails details = new PersonalDetails(dto.getFirstName,dto.getLastName(),...);
        person.updatePersonalDetails(details);
        person.updateAddress(address);
       _personRepository.save(person);
    }
    
    根据和DDD,
    值对象
    (您所称的
    dto
    PersonDetailsDTO
    地址
    )应由域指定。这意味着它们应该位于域名称空间/包/项目中。顺便说一句,那些
    值对象
    可以一直使用到表示层,然后再使用

    其次,它们不是
    dto
    (数据传输对象),因为不涉及昂贵的远程调用,而是
    值对象(内聚数据和可能的行为);了解更多如何不将其用作反模式

    最后但并非最不重要的一点是,您应该使用通用语言中的术语命名方法(
    person.Update
    似乎不是来自UL)。我不是说100%是你的情况,因为我不知道你的领域,我只是说你应该注意这些重要的细节(命名事物)。

    根据和DDD,
    值对象
    (你称之为
    dto
    :persondeailsdo
    地址
    )域应。这意味着它们应该位于域名称空间/包/项目中。顺便说一句,那些
    值对象
    可以一直使用到表示层,然后再使用

    其次,它们不是
    dto
    (数据传输对象),因为不涉及昂贵的远程调用,而是
    值对象(内聚数据和可能的行为);了解更多如何不将其用作反模式


    最后但并非最不重要的一点是,您应该使用通用语言中的术语命名方法(
    person.Update
    似乎不是来自UL)。我不是说100%是你的情况,因为我不知道你的领域,我只是说你应该注意这些重要的细节(命名事物)。

    你需要实现对象到对象的映射。这意味着服务层负责通过映射从客户机接收的DTO实例的值来创建和填充基于DTO的域对象

    您可以利用库简化对象到对象的映射。
    当然,如果需要,可以为域到DTO提供服务。

    您需要实现对象到对象的映射。这意味着服务层负责通过映射从客户机接收的DTO实例的值来创建和填充基于DTO的域对象

    您可以利用库简化对象到对象的映射。
    当然,如果需要,可以为域到DTO提供服务。

    我很确定您不想更新一个人(规则可能有例外,但通常这听起来像CRUD术语,您希望在DDD中避免)。也许是你感兴趣的。是的,这是一个很好的观点,谢谢。我会看一看:)我很确定你不想更新per