我应该如何处理 MediatR NotificationHandlers 的简单注入器生活方式?
How should I handle Simple Injector Lifestyles for MediatR NotificationHandlers?
我有一个 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
class 来解决这个问题,其中 PublishEvents
class 看起来像:
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
口头禅,但除此之外,我想知道是否有更好的方法...
你基本上有三个选择:
- 定义您自己的抽象(正如您目前所做的那样)
- 将默认的
IMediator
实现替换为应用范围的实现
- 用应用范围
的class修饰默认IMediator
实现
所有三个选项都同样好,尽管定义您自己的应用程序抽象通常应该有您的偏好,因为这符合 Dependency Inversion Principle。
我有一个 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
class 来解决这个问题,其中 PublishEvents
class 看起来像:
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
口头禅,但除此之外,我想知道是否有更好的方法...
你基本上有三个选择:
- 定义您自己的抽象(正如您目前所做的那样)
- 将默认的
IMediator
实现替换为应用范围的实现 - 用应用范围 的class修饰默认
IMediator
实现
所有三个选项都同样好,尽管定义您自己的应用程序抽象通常应该有您的偏好,因为这符合 Dependency Inversion Principle。