Ответ 1
С помощью Autofac вам нужно ввести IComponentContext
в диспетчер. Таким образом вы можете вернуться в контейнер для разрешения требуемого обработчика команд:
public class AutofacCommandDispatcher : ICommandDispatcher
{
private readonly IComponentContext context;
public AutofacCommandDispatcher(IComponentContext context)
{
this.context = context;
}
public void Dispatch<TCommand>(TCommand command)
{
var handler = this.context.Resolve<ICommandHandler<TCommand>>();
void handler.Execute(command);
}
}
Вы можете зарегистрировать AutofacCommandDispatcher
следующим образом:
builder.RegisterType<AutofacCommandDispatcher>().As<ICommandDispatcher>();
И вы можете зарегистрировать все свои обработчики команд за один раз следующим образом:
builder.RegisterAssemblyTypes(myAssembly)
.AsClosedTypesOf(typeof(ICommandHandler<>));
Две заметки. Прежде всего, вы, вероятно, определили ICommandHandler<T>
как контравариантный (с ключевым словом in
), потому что Resharper так сказал, но это плохая идея для обработчиков команд. Всегда существует сопоставление "один к одному" между командным и командным обработчиком, но определение ключевого слова in
сообщает, что может быть несколько реализаций.
Во-вторых, на мой взгляд, наличие диспетчера команд - плохая идея, потому что это может скрыть тот факт, что у потребляющих классов обработчиков команд слишком много зависимостей, что является признаком нарушения принципа единой ответственности. Более того, использование такого диспетчера откладывает создание части графического объекта (части обработчика команд) до тех пор, пока фактически не будет выполнена команда (против того, когда потребитель будет разрешен). Это затрудняет проверку конфигурации контейнера. Когда обработчики команд вводятся напрямую, вы точно знаете, что весь граф объекта можно разрешить, когда можно разрешить типы корней в вашей конфигурации. Легко определить команду, но забудьте создать соответствующий обработчик команд, поэтому вам нужно будет добавить для этого единичные тесты, чтобы проверить, имеет ли каждая команда соответствующий обработчик. Вы можете избавиться от необходимости писать такой тест, если вы удалите диспетчера вместе.