Как разрешить различные реализации универсальных обработчиков событий с помощью Autofac - PullRequest
0 голосов
/ 27 апреля 2018

Я новичок в Autofac и не могу привести пример работы приложения подписчика на событие. Не могли бы вы помочь мне смоделировать это?

Идея заключается в следующем.

У меня есть контроллер REST API, где клиенты могут отправлять события POST (реализации IDomainEvent)

Контроллер должен получать ВСЕ введенные классы проектора (обработчики событий), которые будут что-то делать с событиями.

public class EventsController 
    : Controller
{
    private readonly IEnumerable<IEventHandler> _projectors;

    public EventsController(IEnumerable<IEventHandler> projectors)
    {
        _projectors = projectors;
    }

    [HttpPost("EventA")]
    public IActionResult AddEventA([FromBody]EventA evt)
    {
        foreach (var projector in _projectors)
        {
            projector.Handle(evt);
        }
        return Ok();
    }

    [HttpPost("EventB")]
    public IActionResult AddEventB([FromBody]EventB evt)
    {
        foreach (var projector in _projectors)
        {
            projector.Handle(evt);
        }
        return Ok();
    }
}

А потом у меня есть много Проекторов (обработчиков событий), которые делают разные вещи с событиями, на которые они подписываются.

public class ProjectorA : IEventHandler<EventA>, IEventHandler<EventB>
{
    private readonly IRepository _repository;

    public ProjectorA(IRepository repository)
    {
        _repository = repository;
    }

    public void Handle(EventA evt)
    {
        // do something with EventA
    }

    public void Handle(EventB evt)
    {
        // do something with EventB
    }
}

public class ProjectorB : IEventHandler<EventA>
{
    private readonly IRepository _repository;

    public ProjectorA(IRepository repository)
    {
        _repository = repository;
    }

    public void Handle(EventA evt)
    {
        // do something with EventA
    }

    // I don't care about EventB so I don't subscribe to it
}

IEventHandler будет выглядеть примерно так:

public interface IEventHandler<in TDomainEvent>
    : IEventHandler
    where TDomainEvent : IDomainEvent
{
    void Handle(TDomainEvent evt);
}

Как изменить это моделирование и как зарегистрировать мои проекторы в Autofac, чтобы использовать его аналогичным образом?

Заранее спасибо!

1 Ответ

0 голосов
/ 27 апреля 2018

Если у вас есть только 2 типа Event, проще всего было бы иметь 2 зависимости

public class EventsController 
    : Controller
{
    private readonly IEnumerable<IEventHandler<EventA>> _Aprojectors;
    private readonly IEnumerable<IEventHandler<EventB>> _Bprojectors;

    public EventsController(IEnumerable<IEventHandler<EventA>> Aprojectors,
                            IEnumerable<IEventHandler<EventB>> Bprojectors)
    {
        _Aprojectors = Aprojectors;
        _Bprojectors = Bprojectors;
    }

    // ...
}

Но если вам нужно универсальное решение, самый простой способ - создать универсальный репозиторий

public class EventsController<TEvent> 
    : Controller
    where TEvent : IEvent 
{
    private readonly IEnumerable<IEventHandler<TEvent>> _projectors;

    public EventsController(IEnumerable<IEventHandler<Event>> projectors)
    {
        _projectors = projectors;
    }

    [HttpPost()]
    public IActionResult AddEvent([FromBody]TEvent evt)
    {
        foreach (var projector in _projectors)
        {
            projector.Handle(evt);
        }
        return Ok();
    }
}

и объявите свой EventHandler вот так

builder.RegisterType<ProjectorA>().As<IEventHandler<AEvent>>();
builder.RegisterType<ProjectorB>().As<IEventHandler<BEvent>>();

Общий контроллер не реализован по умолчанию в ASP.net MVC. Для ядра ASP.net этот пост https://stackoverflow.com/a/45698048/814735 содержит отличное объяснение того, как реализовать такой универсальный контроллер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...