具有多个构造函数的单个DTO—这看起来像一个合适的解决方案吗?

本文关键字:一个 解决方案 看起来 构造函数 单个 DTO | 更新日期: 2023-09-27 18:04:00

我有一个名为"Set"的实体,其中包含Cards。有时我想看到整个纸牌及其内容(纸牌视图),有时我只想知道Set中有多少张纸牌(表格视图)。在我努力保持DRY的过程中,我决定尝试重用SetDto类和多个构造函数,像这样:

public class SetDto
    {
        public SetDto()
        {
            Cards = new List<CardDto>();
        }
        // Called via SetDto(set, "thin")
        public SetDto (Set set, string isThin)
        {
            var setDto = new SetDto()
                {
                    SetId = set.SetId,
                    Title = set.Title,
                    Details = set.Details,
                    Stage = set.Stage,
                    CardCount = set.Cards.Count
                };
            return setDto;
        }
        // Called via SetDto(set)
        public SetDto(Set set)
        {
            SetId = set.SetId;
            UserId = set.UserId;
            Title = set.Title;
            Details = set.Details;
            FolderId = set.FolderId;
            Stage = set.Stage;
            IsArchived = set.IsArchived;
            Cards = new List<CardDto>();
            foreach (Card card in set.Cards)
            {
                Cards.Add(new CardDto(card));
            }
        }
        /// property definitions

我最初有两个不同的dto集- ThinSetDto和FullSetDto -但这似乎混乱和更难测试。上面的解决方案看起来还行吗,还是我打破了已知的最佳实践?感谢您的宝贵时间!

具有多个构造函数的单个DTO—这看起来像一个合适的解决方案吗?

我将在SetManager类(处理CRUD操作的类)中创建三个方法,而不是在DTO中。

dto内部不应该有这样的逻辑。无论如何,我同意你的观点,复制是无用的(而且是邪恶的)。

public class BaseSetDTO
{
  public BaseSetDTO()
  {
    Set();
  }
  internal virtual void Set()
  {
    //Do your base set here with base properties
  }
}
public class SetDTO : BaseSetDTO
{
  internal override void Set()
  {
    //Do a full set here
  }
}

创建一个基类,然后让类型处理它们应该设置的内容。为你的ThinSetDTO创建一个新的on,并重新覆盖。

相反,我更喜欢通过在Set类中声明所有属性并通过传递所需参数来修改属性的扩展方法。否则,初始化baseDTO并通过添加所需属性和调用扩展方法来创建所需版本的DTO并返回baseDTO,从而获得各种版本。

public static Set SetDto(this Set set, bool isThin)
{
  if(isThin)
  {
  }  

   return objSet;
}

一个常见的解决方案是让存储库(或等效)通过具有不同的访问方法(例如:Get() ... GetSet())返回您想要的DTO/实体的"风味",或者枚举您的"风味"实体的问题并将其传递给您的"Get"(或等效)方法,例如:

enum ContactCollectionFlavors { Full, CountOnly, CountWithNames .... }
...
foo = ContactRepository.GetByLastName('Jones', ContactCollectionFlavors.CountWithNames);

这可能会变得有点混乱,从经验来看,有问题的实体应该有一些方法知道它是什么"味道",这闻起来很糟糕,因为它打破了封装和分离的关注-但在我看来,它最好抓住你的鼻子,保留一些带外数据,这样以后你可以有延迟加载的实体,允许你把"轻口味"变成完全填充的实体。