Как мне обращаться с простыми образами жизни для MediatR NotificationHandlers? - PullRequest
0 голосов
/ 03 мая 2019

У меня есть ASP.NET Web API, использующий MediatR и SimpleInjector.

Они зарегистрированы так:

_container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();
_container.Options.DefaultLifestyle = Lifestyle.Scoped;

_container.Collection.Register(typeof(INotificationHandler<>), typesFound);

Я могу публиковать события из моего Controllers:

[HttpGet]
public ActionResult<...> Get()
{
    _mediator.Publish(new SomeEvent());
}

Это прекрасно работает!

Новым требованием является прослушивание обновлений из внешней системы (Tibco). Когда происходит обновление, уведомление приходит через событие C # из другого потока. В обработчике событий C # я хочу использовать MediatR для Publish уведомления:

void callbackFromTibco(object listener, MessageReceivedEventArgs @args)
{
    _mediatr.Publish(new SomeEvent();
}

Именно в этот момент SimpleInjector выдает исключение:

SomeEventHandler is registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope.

Это потому, что стек вызовов происходит из другого потока, тогда как в Controller сам контроллер был ограничен SimpleInjector, и, следовательно, MediatR создает обработчик в той же области.

Можно ли что-то сделать, чтобы я мог зарегистрировать обработчики событий для использования в обоих случаях?

Я справился с этим, создав интерфейс IPublishEvents и класс PublishEvents, где класс PublishEvents выглядит следующим образом:

public PublishEvents(Container container, IMediator mediator)
{
    _container = container;
    _mediator = mediator;
}

public Task Publish(object notification, CancellationToken cancellationToken = default)
{
    using (AsyncScopedLifestyle.BeginScope(_container))
    {
        return _mediator.Publish(notification, cancellationToken);
    }
}

Является ли абстракция правильным подходом? Это, конечно, соответствует Don't Marry the Framework мантре, но кроме этого, я хотел бы знать, есть ли лучший способ ...

1 Ответ

1 голос
/ 06 мая 2019

В основном у вас есть три варианта:

  • Определите свою собственную абстракцию (как вы делаете в настоящее время)
  • Замените реализацию IMediator по умолчанию на реализацию, которая применяет область видимости
  • Украсьте реализацию IMediator по умолчанию классом, который применяет область видимости

Все три параметра одинаково хороши, хотя определение собственных абстракций приложения обычно должно иметь ваши предпочтения, поскольку это соответствует Принцип обращения зависимостей .

...