Вложенные DTO в шаблоне Command-Handler?

В настоящее время я реализую шаблон Command-Handler для службы, которую я разрабатываю, где команда по сути является DTO для метода .Handle() обработчика. До этого момента все было довольно прямолинейно, но я столкнулся с вопросом реализации, который поставил меня в тупик относительно его запаха.

Должен ли я создавать интерфейсы, которые расширяют ICommand дополнительными специфическими данными, необходимыми для соответствующего CommandHandler... или мне следует создать свойство .Data в интерфейсе ICommand для доступа к вложенному объекту 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, которые в противном случае были бы реализованы из более кратких интерфейсов.


person arjo.reich    schedule 18.04.2014    source источник


Ответы (1)


Я думаю, что второй вариант теряет суть наличия специализированных команд. Вы также можете переименовать DeleteProjectLogCommand в CRUDCommand. Кроме того, вы как бы ограничиваете возможности своей реализации, вводя общую полезную нагрузку DataDto в ICommand, которая, кстати, во многих случаях может не понадобиться. И ваш ProjectDto заботится о том, какими должны быть свойства вашей команды.

Я бы остановился на вашем первом варианте. Более того, я бы, наверное, избавился от IDeleteProjectCommand, чтобы было проще.

person jnovo    schedule 18.04.2014