Несколько типов для SetHandlerInterface() с мембраной и контейнером ioc
Переходя к демонстрационному коду CQRS здесь, команды и обработчики событий разводятся отдельно, как показано ниже:
public interface CommandHandler<in T>
{
void Handle(T command);
}
public interface EventHandler<in T>
{
void Handle(T @event);
}
bus = BusSetup.StartWith<Conservative>()
.Apply<FlexibleSubscribeAdapter>(a =>
{
a.ByInterface(typeof(IHandleEvent<>));
a.ByInterface(typeof(IHandleCommand<>));
})
.Construct();
Я использую контейнер IoC, подключенный с помощью membus, и он реализует мечту, реализуя IEnumerable<object> GetAllInstances(Type desiredType)
интерфейс с моим контейнером, однако в отличие от демонстрации с этим методом регистрации я не могу разделить интерфейсы для отдельных команд и событий:
this.Bus = BusSetup.StartWith<Conservative>()
.Apply <IoCSupport>(c =>
{
c
.SetAdapter(SimpleInjectorWiring.Instance)
.SetHandlerInterface(typeof(CommandHandler<>))
/*.SetHandlerInterface(typeof(EventHandler<>))*/;
// only CommandHandler or EventHandler can be used - not both
})
.Construct();
Может кто-нибудь, пожалуйста, дайте мне знать, есть ли способ обойти это, чтобы мы могли зарегистрироваться на произвольное количество типов?
2 ответа
Я боюсь, что текущая версия MemBus не может сделать это - без особой причины, заметьте. Я знаю, что имеет смысл различать события и команды, даже если базовая инфраструктура одинакова.
Единственный способ обойти это сейчас - использовать единственный интерфейс для подключения IOC к MemBus.
Если такая функция должна быть введена в MemBus, нужно подумать, как должен выглядеть механизм поиска в контейнере IOC. Вероятно, потребуется запросить все обработчики всех интерфейсов, или потребуется ввести какой-либо способ классификации / различения событий и командных "сообщений".
Я просто настроил это для подтверждения концепции, потому что я использую следующее соглашение в соответствии с рекомендациями Microsoft CQRS Journey:
- На команду может быть только один CommandHandler
- Может быть много EventHandlers на событие
Я хотел использовать API контейнера IOC (SimpleInjector), чтобы обеспечить соблюдение соглашения, поскольку оно заставляет вас делать регистрации одного или нескольких обработчиков явными в зависимости от конструкции. Теперь мой контейнер IOC будет выдавать исключение всякий раз, когда два обработчика для одной и той же команды будут случайно зарегистрированы.
Чтобы MemBus поддерживал это соглашение, мне нужно было создать собственные ISetup, ISubscriptionResolver и IoCAdapter (начиная с кода из IoCSupport, IoCBasedResolver и IocAdapter соответственно). Мне также пришлось создать новый интерфейс IocAdapter, который также поддерживает единственный метод GetInstance(); теперь интерфейс примерно соответствует интерфейсу System.Web.Http.Dependencies.IDependencyScope (GetService и GetServices).
// Setup
return BusSetup
.StartWith<Conservative>()
.Apply<CommandingEventingSupport>(
adapter =>
{
adapter.SetAdapter(new MemBusSimpleInjectorAdapter(container));
adapter.SetCommandHandlerInterface(typeof(IHandleCommand<>));
adapter.SetEventHandlerInterface(typeof(IHandleEvent<>));
adapter.SetCommandTest(obj => obj is IDomainCommand);
})
.Construct();
Затем распознаватель отправляет команды в GetInstance и события в GetAllInstances...
// Command vs Event
public IEnumerable<ISubscription> GetSubscriptionsFor(object message)
{
bool isCommand = _isCommandFunc(message);
Type typeToCreate = isCommand
? _commandHandlerType
: _eventHandlerType;
var handlesType = ConstructHandlesType(typeToCreate, message.GetType());
var mi = handlesType.GetRuntimeMethods().First();
return isCommand
? new[] { mi.ConstructSubscription(_adapter.GetInstance(handlesType)) }
: _adapter.GetAllInstances(handlesType).Select(mi.ConstructSubscription);
}