У меня есть немного уродливый кусок кода, потому что я должен использовать отражение, чтобы заставить его работать.Я не могу не задаться вопросом, есть ли лучший / более чистый способ достижения того же самого.
Сценарий следующий: мой код подписывается на хранилище событий.Каждый раз, когда хранилище событий записывает новое событие, выполняется мой метод Task Process(IResolvedEvent resolvedEvent)
.В настоящее время я сопоставляю (десериализуем) resolvedEvent
с его исходным IPersistableEvent
и использую его тип для получения из контейнера DI (Autofac) зарегистрированного IEventHandler<TEvent> where TEvent : IPersistableEvent
, чтобы я мог обработать это событие с ним.
Как видите, тип события известен только во время выполнения, и мне приходится использовать отражение дважды.Первый раз использовать фабрику, которая получает правильные IEventHandler<TEvent>
из контейнера DI, и второй раз вызвать метод Handle
в этом экземпляре.
Основная проблема Я бы хотелк рефакторингу относится тот факт, что метод Invoke
возвращает объект, и я хочу привести этот объект к IEventHandler<TEvent>
, где я знаю TEvent
во время выполнения .
Было бы здоровоесли бы я мог сделать что-то вроде этого, это C #:
var eventHandler = (IEventHandler<?>)createMethodGeneric.Invoke(_eventHandlerFactory, null);
await eventHandler.Handle(persistableEvent);
К сожалению, я не могу преобразовать это в универсальный класс таким образом.Можно ли делать литье по-другому с отражением или желательно без отражения?Это мой текущий рабочий код.
public class ResolvedEventDispatcher
: IResolvedEventDispatcher
{
private readonly IMapper<IResolvedEvent, IPersistableEvent> _persistableEventMapper;
private readonly IEventHandlerFactory _eventHandlerFactory;
public ResolvedEventDispatcher(
IMapper<IResolvedEvent, IPersistableEvent> persistableEventMapper,
IEventHandlerFactory eventHandlerFactory)
{
_persistableEventMapper = persistableEventMapper;
_eventHandlerFactory = eventHandlerFactory;
}
public async Task Process(IResolvedEvent resolvedEvent)
{
try
{
var persistableEvent = _persistableEventMapper.Map(resolvedEvent);
var persistableEventType = persistableEvent.GetType();
var eventHandlerFactoryType = _eventHandlerFactory.GetType();
var createMethod =
eventHandlerFactoryType
.GetMethods()
.First(x => x.IsGenericMethod);
var typeArguments =
new[]
{
persistableEventType
};
var createMethodGeneric = createMethod.MakeGenericMethod(typeArguments);
var eventHandler = createMethodGeneric.Invoke(_eventHandlerFactory, null);
var eventHandlerType = eventHandler.GetType();
var handleMethod = eventHandlerType.GetMethod("Handle");
var parameters =
new object[]
{
persistableEvent
};
await (Task) handleMethod.Invoke(eventHandler, parameters);
}
catch (Exception exception)
{
var foo = exception;
}
}
}
И это фабрика, которую я использую для получения правильного IEventHandler<TEvent>
из контейнера DI:
public class EventHandlerFactory
: IEventHandlerFactory
{
private readonly IComponentContext _componentContext;
public EventHandlerFactory(IComponentContext componentContext)
{
_componentContext = componentContext;
}
public IEventHandler<TEvent> Create<TEvent>() where TEvent : class, IPersistableEvent
{
var eventType = typeof(TEvent);
var eventHandlerType = typeof(IEventHandler<>);
var typeArguments =
new[]{
eventType
};
var eventHandlerWithGenericType = eventHandlerType.MakeGenericType(typeArguments);
var isRegistered = _componentContext.IsRegistered(eventHandlerWithGenericType);
if (!isRegistered)
{
throw new EventHandlerNotRegisteredException($"Could not find any handler for event type {eventType}");
}
var eventHandler = _componentContext.Resolve(eventHandlerWithGenericType);
return (IEventHandler<TEvent>)eventHandler;
}
}
Наконец, обработчик Iхочу вызвать определяется:
public interface IEventHandler<in TEvent>
where TEvent : IPersistableEvent
{
Task Handle(TEvent @event);
}