CQRS шаблон - интерфейсы
Я новичок в паттерне CQRS, но я хотел бы понять, почему вы должны использовать два интерфейса:
public interface IQuery{}
public interface ICommand{}
Вместо одного интерфейса (например, IExecutable или что-то еще ...)
Чем у вас также есть один обработчик (например, IExecutionHandler или любой другой ...)
И если вы хотите, вы все равно можете разделить его на ICommandExecutionHandler и IQueryExecutionHandler
Обновление: попытка
Следующий код - просто пример того, как я это вижу. Вполне возможно, что я совершенно не прав в этом ... поэтому, пожалуйста, поделитесь своими проблемами / моими ошибками. Я просто пытаюсь понять это.
public interface IExecutable { }
public interface ICommand : IExecutable { }
public interface IReturnCommand<TOutput>: ICommand
{
TOutput Result { get; set; }
}
public interface IQuery<TOutput>: IExecutable
{
TOutput Result { get; set; }
}
public interface IExecutionHandler<in T>: IDisposable where T : IExecutable
{
void Execute(T executable);
}
public class CreateAttachments : IReturnCommand<List<Guid>>
{
public List<Attachment> Attachments { get; set; }
public List<Guid> Result { get; set; }
}
public abstract class BaseExecutionHandler : IDisposable
{
protected readonly IUnitOfWork UnitOfWork;
private bool _disposed;
protected BaseExecutionHandler(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
UnitOfWork.Dispose();
}
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
public class AttachmentCommandHandler : BaseExecutionHandler,
IExecutionHandler<CreateAttachments>
{
public AttachmentCommandHandler(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
public void Execute(CreateAttachments command)
{
command.Result = command.Attachments.Select(x => UnitOfWork.Create(x)).ToList();
}
}
public interface IProcessor : IDisposable
{
void Process<TExecutable>(TExecutable command) where TExecutable : IExecutable;
}
public class Processor : IProcessor
{
private readonly Dictionary<IExecutable, IExecutionHandler<IExecutable>> _handlers;
private readonly IUnitOfWork _unitOfWork;
private bool _disposed;
public Processor(IUnitOfWork unitOfWork)
{
_handlers = new Dictionary<IExecutable, IExecutionHandler<IExecutable>>();
_unitOfWork = unitOfWork;
}
private IExecutionHandler<IExecutable> GetHandler<TExecutable>(TExecutable executable) where TExecutable: IExecutable
{
if (_handlers.ContainsKey(executable))
{
return _handlers[executable];
}
var handlerType = typeof(IExecutionHandler<>).MakeGenericType(executable.GetType());
var handler = Activator.CreateInstance(handlerType, _unitOfWork) as IExecutionHandler<IExecutable>;
_handlers.Add(executable, handler);
return handler;
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
foreach (var handler in _handlers.Values)
{
handler.Dispose();
}
}
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Process<TExecutable>(TExecutable executable) where TExecutable : IExecutable
{
var handler = GetHandler(executable);
handler.Execute(executable);
}
}
public class AttachmentController : ApiController
{
private readonly IProcessor _processor;
public AttachmentController(IProcessor processor)
{
_processor = processor;
}
public List<Guid> Post(List<Attachment> attachments)
{
var command = new CreateAttachments { Attachments = attachments };
_processor.Process(command);
return command.Result;
}
[EnableQuery]
public IQueryable<Attachment> Get()
{
var query = new GetAllAttachments { };
_processor.Process(query);
return query.Result;
}
protected override void Dispose(bool disposing)
{
_processor.Dispose();
base.Dispose(disposing);
}
}