【问题标题】:Nested DTOs in the Command-Handler Pattern?命令处理程序模式中的嵌套 DTO?
【发布时间】:2023-06-29 20:18:01
【问题描述】:

我目前正在为我正在设计的服务实现命令处理程序模式,其中命令本质上是处理程序的 .Handle() 方法的 DTO。到目前为止,一切都很简单,但我遇到了一个实施问题,让我对它的气味持观望态度。

我应该创建接口来扩展 ICommand 并为其对应的 CommandHandler 所需的额外特定数据...还是应该在 ICommand 接口上创建一个 .Data 属性来访问嵌套的 Dto 对象?

选项 #1

public interface ICommand
{
    Guid Id { get; set; }
    string Name { get; set; }
    CommandStatus Status { get; set; }
    TimeSpan Elapsed { get; set; }
}

[KnownType(typeof (DeleteProjectLogCommand))]
[DataContract(Name = "Command")]
public abstract class CommandBase : ICommand
{
    [DataMember]
    public Guid Id { get; set; }
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public CommandStatus Status { get; set; }
    [DataMember]
    public TimeSpan Elapsed { get; set; }
}

public interface IDeleteProjectCommand : ICommand
{
    long? ProjectId { get; set; }
}

[DataContract(Name = "DeleteProjectLogCommand")]
public class DeleteProjectLogCommand : CommandBase, IDeleteProjectCommand
{
    [DataMember]
    public long? ProjectId { get; set; }
}

选项 #2

public interface ICommand
{
    Guid Id { get; set; }
    string Name { get; set; }
    CommandStatus Status { get; set; }
    TimeSpan Elapsed { get; set; }
    DataDto Data { get; set; }
}

[KnownType(typeof(ProjectDto))]
[DataContract(Name = "DataDto")]
public abstract class DataDto
{
    [DataMember]
    long? Id { get; set; }
    bool IsNew { get; set; }
}

public class ProjectDto : DataDto
{
    public long? OrganizationId { get; set;}
    public ProjectType ProjectType { get; set;}
    // ...etc
}

[DataContract(Name = "DeleteProjectLogCommand")]
public class DeleteProjectLogCommand : CommandBase
{
    // ...in this instance no other data is needed, 
    // making this basically just an empty Decorator of CommandBase
}

第二个例子有点 DRY'er,但它的代价是拥有更胖的 DataContracts 和大量现在空的抽象 CommandBase 装饰,否则这些装饰本来可以从更简洁的接口实现。

【问题讨论】:

    标签: c# dto datacontract command-pattern


    【解决方案1】:

    我认为第二种选择失去了拥有专门命令的本质。您也可以将DeleteProjectLogCommand 重命名为CRUDCommand。此外,您通过在ICommand 中引入通用的DataDto 有效负载来限制实现的功能,顺便说一下,在许多情况下可能不需要。而您的 ProjectDto 负责处理您的命令属性。

    我会坚持你的第一个选择。更重要的是,我可能会删除 IDeleteProjectCommand 以使其更简单。

    【讨论】:

      最近更新 更多