В настоящее время я реализую шаблон 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, которые в противном случае были бы реализованы из более кратких интерфейсов.