将 Mediatr 与 Autofac 集成
Integrate Mediatr with Autofac
我正在使用 .NET Core(注意:不是 Web 环境)。我需要集成 MediatR 和 Autofac。
wiki has a guide and StructureMap example. Also, an Autofac sample, which I've simplified. There's no mention of lifetime scopes, but in a separate project,我发现了有用的评论,并将其转换为Autofac。周围有很多代码示例,每个都不同。
到目前为止我得到了什么:
// enables contravariant Resolve() for interfaces with single contravariant ("in") arg
builder
.RegisterSource(new ContravariantRegistrationSource());
// mediator itself
builder
.RegisterType<Mediator>()
.As<IMediator>()
.InstancePerLifetimeScope();
// request handlers
builder
.Register<SingleInstanceFactory>(context => {
var ctx = context.Resolve<IComponentContext>(); // unsure why needed, but it works
return t => { object o; return ctx.TryResolve(t, out o) ? o : null; };
})
.InstancePerLifetimeScope();
// notification handlers
builder
.Register<MultiInstanceFactory>(context => {
var ctx = context.Resolve<IComponentContext>(); // unsure why needed, but it works
return t => (IEnumerable<object>)ctx.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
})
.InstancePerLifetimeScope();
然后注册我的自定义内容:
- 临时处理程序,即
InstancePerDependency()
- pre/post-processors 根据要求,即
InstancePerLifetimeScope()
- 行为是短暂的,即
InstancePerDependency()
例如
builder.RegisterType<EditCommandHandler>().AsImplementedInterfaces().InstancePerDependency();
然而,在我见过的大多数代码示例中,尤其是对于 StructureMap,还有大量其他注册(例如 IRequestHandler<,>
、IRequestHandler<>
、IAsyncRequestHandler<,>
、IAsyncRequestHandler<>
、ICancellableAsyncRequestHandler<,>
、ICancellableAsyncRequestHandler<>
、INotificationHandler<>
、IAsyncNotificationHandler<>
、ICancellableAsyncNotificationHandler<>
),ASP.NET Core container's 集成也极其复杂。我没有做过类似的事情。
如果您有此 在生产中工作 ,您的配置与我的相比如何?谢谢!
TL;DR;
我觉得你的注册没问题。
告诉我更多 - 也就是让我们一个一个回答你的问题
您当前的注册
MediatR 需要您注册 SingleInstanceFactory
和 MultiInstanceFactory
,因为 Mediator
class.
需要它们
然后你需要注册你的处理程序和行为,你这样做了,所以你没问题。
我可以做的一个评论是,看你的例子,你似乎一个一个地注册你的处理程序。虽然这是有效的 - 这是最重要的,但这意味着每次添加新的 request/handler 对时,您都必须在 Autofac 容器中注册处理程序。
我建议转向基于约定的注册方式,Autofac 开箱即用地支持这种方式。假设您的应用程序使用异步请求处理程序和异步通知处理程序,您可以这样写:
var openHandlersTypes = new[] { typeof(IAsyncRequestHandler<,>), typeof(IAsyncNotificationHandler<,>) };
foreach (var openHandlerType in openHandlersTypes)
{
builder
.RegisterAssemblyTypes(ThisAssembly)
.AsClosedTypesOf(openHandlerType)
.InstancePerDependency();
}
Autofac 将扫描 ThisAssembly
并注册关闭 openHandlersTypes
中存在的开放泛型类型的所有类型。
关于所有处理程序类型
您担心您没有注册 MediatR 公开的所有处理程序类型。那很好。如果您不使用可取消处理程序,则无需注册它们。您可以选择要实现的处理程序类型。当您向 MediatR 发送请求时,它将使用提供的 MultiInstanceFactory
来确定您的处理程序是同步处理程序、异步处理程序还是可取消的异步处理程序。
另外,请注意所有请求处理程序类型都有两种类型。只有 one generic type like IRequestHandler<TRequest>
do not return a value, whereas the ones that have two generic parameters like IRequestHandler<TRequest, TResponse>
return 值的那些。但是您的注册将取决于您是否使用它们。
ASP.NET 核心集成部分
你用的是Autofac,不用担心。如果您使用 ASP.NET Core DI 容器,该包旨在帮助您注册处理程序。它当然很复杂,因为它会执行程序集扫描以查找代码中的所有处理程序并为您注册它们。但同样,您不必担心,因为您使用的是另一个容器。
对于发现此问题的任何人 post:我不久前创建了一个 nuget-package 作为 AutoFac ContainerBuilder
的扩展。
我知道有一个基于 Microsofts-DI 的,但我的已与 AutoFac 完全集成,并且与 ASP.NET-Core 也能完美工作。
您需要做的就是调用容器构建器上的扩展方法并传入一个或多个程序集。
builder.AddMediatR(typeof(Startup).Assembly);
我正在使用 .NET Core(注意:不是 Web 环境)。我需要集成 MediatR 和 Autofac。
wiki has a guide and StructureMap example. Also, an Autofac sample, which I've simplified. There's no mention of lifetime scopes, but in a separate project,我发现了有用的评论,并将其转换为Autofac。周围有很多代码示例,每个都不同。
到目前为止我得到了什么:
// enables contravariant Resolve() for interfaces with single contravariant ("in") arg
builder
.RegisterSource(new ContravariantRegistrationSource());
// mediator itself
builder
.RegisterType<Mediator>()
.As<IMediator>()
.InstancePerLifetimeScope();
// request handlers
builder
.Register<SingleInstanceFactory>(context => {
var ctx = context.Resolve<IComponentContext>(); // unsure why needed, but it works
return t => { object o; return ctx.TryResolve(t, out o) ? o : null; };
})
.InstancePerLifetimeScope();
// notification handlers
builder
.Register<MultiInstanceFactory>(context => {
var ctx = context.Resolve<IComponentContext>(); // unsure why needed, but it works
return t => (IEnumerable<object>)ctx.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
})
.InstancePerLifetimeScope();
然后注册我的自定义内容:
- 临时处理程序,即
InstancePerDependency()
- pre/post-processors 根据要求,即
InstancePerLifetimeScope()
- 行为是短暂的,即
InstancePerDependency()
例如
builder.RegisterType<EditCommandHandler>().AsImplementedInterfaces().InstancePerDependency();
然而,在我见过的大多数代码示例中,尤其是对于 StructureMap,还有大量其他注册(例如 IRequestHandler<,>
、IRequestHandler<>
、IAsyncRequestHandler<,>
、IAsyncRequestHandler<>
、ICancellableAsyncRequestHandler<,>
、ICancellableAsyncRequestHandler<>
、INotificationHandler<>
、IAsyncNotificationHandler<>
、ICancellableAsyncNotificationHandler<>
),ASP.NET Core container's 集成也极其复杂。我没有做过类似的事情。
如果您有此 在生产中工作 ,您的配置与我的相比如何?谢谢!
TL;DR;
我觉得你的注册没问题。
告诉我更多 - 也就是让我们一个一个回答你的问题
您当前的注册
MediatR 需要您注册 SingleInstanceFactory
和 MultiInstanceFactory
,因为 Mediator
class.
然后你需要注册你的处理程序和行为,你这样做了,所以你没问题。
我可以做的一个评论是,看你的例子,你似乎一个一个地注册你的处理程序。虽然这是有效的 - 这是最重要的,但这意味着每次添加新的 request/handler 对时,您都必须在 Autofac 容器中注册处理程序。
我建议转向基于约定的注册方式,Autofac 开箱即用地支持这种方式。假设您的应用程序使用异步请求处理程序和异步通知处理程序,您可以这样写:
var openHandlersTypes = new[] { typeof(IAsyncRequestHandler<,>), typeof(IAsyncNotificationHandler<,>) };
foreach (var openHandlerType in openHandlersTypes)
{
builder
.RegisterAssemblyTypes(ThisAssembly)
.AsClosedTypesOf(openHandlerType)
.InstancePerDependency();
}
Autofac 将扫描 ThisAssembly
并注册关闭 openHandlersTypes
中存在的开放泛型类型的所有类型。
关于所有处理程序类型
您担心您没有注册 MediatR 公开的所有处理程序类型。那很好。如果您不使用可取消处理程序,则无需注册它们。您可以选择要实现的处理程序类型。当您向 MediatR 发送请求时,它将使用提供的 MultiInstanceFactory
来确定您的处理程序是同步处理程序、异步处理程序还是可取消的异步处理程序。
另外,请注意所有请求处理程序类型都有两种类型。只有 one generic type like IRequestHandler<TRequest>
do not return a value, whereas the ones that have two generic parameters like IRequestHandler<TRequest, TResponse>
return 值的那些。但是您的注册将取决于您是否使用它们。
ASP.NET 核心集成部分
你用的是Autofac,不用担心。如果您使用 ASP.NET Core DI 容器,该包旨在帮助您注册处理程序。它当然很复杂,因为它会执行程序集扫描以查找代码中的所有处理程序并为您注册它们。但同样,您不必担心,因为您使用的是另一个容器。
对于发现此问题的任何人 post:我不久前创建了一个 nuget-package 作为 AutoFac ContainerBuilder
的扩展。
我知道有一个基于 Microsofts-DI 的,但我的已与 AutoFac 完全集成,并且与 ASP.NET-Core 也能完美工作。
您需要做的就是调用容器构建器上的扩展方法并传入一个或多个程序集。
builder.AddMediatR(typeof(Startup).Assembly);