У меня проблемы с разрешением реализации универсального интерфейса во время выполнения.Я работаю с шиной событий, которая разрешает обработчики событий в зависимости от типа события.Когда я пытаюсь разрешить обработчики событий без универсальной реализации, все работает как положено.Я хочу реализовать универсальный интерфейс, чтобы у меня был базовый класс, который обрабатывает события определенного типа.
У меня была следующая ситуация перед созданием универсальной реализации:
public interface IEvent
{
Guid EntityId { get; set; }
}
public interface IEventHandler<TEvent> where TEvent : IEvent
{
Task Handle(TEvent @event);
}
public class EventBus
{
private readonly IComponentContext _context;
public EventBus(IComponentContext context)
{
_context = context;
}
public async Task HandleEvent<TEvent>(TEvent @event) where TEvent : IEvent
{
var handler = _context.Resolve<IEventHandler<TEvent>>();
await handler.Handle(@event);
}
}
Я регистрируюсьeventHandlers следующим образом:
builder.RegisterAssemblyTypes(ThisAssembly).AsClosedTypesOf(typeof(IEventHandler<>));
Пример реализации:
public class FooEventHandler :
IEventHandler<FooArchivedEvent>,
IEventHandler<FooRestoredEvent>,
IEventHandler<FooSomethingElseHappenedEvent>
{
private readonly IRepository<Foo> _repository;
public FooEventHandler(IRepository<Foo> repository)
{
_repository = repository;
}
public async Task Handle(FooArchivedEvent @event)
{
var Foo = await _repository.Get(@event.EntityId);
Foo.Archive();
}
public async Task Handle(FooRestoredEvent @event)
{
var Foo = await _repository.Get(@event.EntityId);
Foo.Restore();
}
public async Task Handle(FooSomethingElseHappenedEvent @event)
{
// do something else with Foo
}
}
public class BarEventHandler :
IEventHandler<BarArchivedEvent>,
IEventHandler<BarRestoredEvent>
{
private readonly IRepository<Bar> _repository;
public BarEventHandler(IRepository<Bar> repository)
{
_repository = repository;
}
public async Task Handle(BarArchivedEvent @event)
{
var Bar = await _repository.Get(@event.EntityId);
Bar.Archive();
}
public async Task Handle(BarRestoredEvent @event)
{
var Bar = await _repository.Get(@event.EntityId);
Bar.Restore();
}
}
Когда я передаю FooArchivedEvent в шину событий, шина событий разрешает требуемый обработчик событий.Как видите, у меня есть некоторый дублирующий код, который я хочу разрешить в базовом обработчике событий.Это то, что я пробовал, прежде чем создать универсальную реализацию (которая не будет компилироваться):
public class BaseEventHandler<TEntity, TArchivedEvent, TRestoredEvent> :
IEventHandler<TArchivedEvent>,
IEventHandler<TRestoredEvent>
where TEntity : class
where TArchivedEvent : IEvent
where TRestoredEvent : IEvent
{
public Task Handle(TArchivedEvent @event)
{
throw new NotImplementedException();
}
public Task Handle(TRestoredEvent @event)
{
throw new NotImplementedException();
}
}
Итак, я создал базовый базовый класс, который выполняет компиляцию, однако я не могу понять, как разрешитьуниверсальный обработчик событий в eventbus.Общий базовый класс:
public abstract class BaseEventHandler<TEntity> :
IEventHandler<IArchivedEvent<TEntity>>,
IEventHandler<IRestoredEvent<TEntity>>
where TEntity : Archivable
{
protected readonly IRepository<TEntity> _repository;
public BaseEventHandler(IRepository<TEntity> repository)
{
_repository = repository;
}
public virtual async Task Handle(IArchivedEvent<TEntity> @event)
{
var entity = await _repository.Get(@event.EntityId);
entity.Archive();
}
public async virtual Task Handle(IRestoredEvent<TEntity> @event)
{
var entity = await _repository.Get(@event.EntityId);
entity.Archive();
}
}
Мой новый FooEventHandler теперь будет выглядеть следующим образом:
public class FooEventHandler : BaseEventHandler<Foo>,
IEventHandler<FooSomethingElseHappenedEvent>
{
public FooEventHandler(IRepository<Foo> repository) : base(repository)
{
}
public Task Handle(FooSomethingElseHappenedEvent @event)
{
// do something else with Foo
}
}
Теперь, когда я передаю FooArchivedEvent в шину событий, шина событий не может разрешить обработчик событий.Есть ли что-то, что мне нужно сделать в части регистрации, или невозможно разрешить общую реализацию, подобную этой?