MediatR多DI容器集成指南:Autofac、DryIoc、Lamar等7大容器接入清单
2026/9/19 23:16:17 网站建设 项目流程

MediatR多DI容器集成指南:Autofac、DryIoc、Lamar等7大容器接入清单

【免费下载链接】MediatRSimple, unambitious mediator implementation in .NET项目地址: https://gitcode.com/gh_mirrors/me/MediatR

MediatR是 .NET 中一款简洁、无依赖的中介者(Mediator)实现,支持请求/响应、命令、查询、通知与流式请求。而"MediatR 如何接入 Autofac、DryIoc、Lamar 等第三方依赖注入(DI)容器"是不少新手上手的第一个坎——官方内置的AddMediatR只对 Microsoft DI 生效。本文给出一份7 大容器接入清单:每种容器要注册哪些类型、流水线(Pipeline)行为如何挂载、有哪些容易踩的坑,全部对照仓库内可运行的官方示例讲解。

想跟着动手的话,先克隆仓库:

git clone https://gitcode.com/gh_mirrors/me/MediatR

所有示例都在 samples/ 目录下,用MediatR.slnx打开即可逐个运行验证。

一、为什么第三方容器需要"手动接入"?

MediatR 的核心只依赖一个IServiceProvider。它在任何容器里要正常工作,只需要满足 4 件事:

  1. 能解析出IMediator(内部实现 Mediator.cs)
  2. 能解析出IEnumerable<IRequestHandler<TRequest, TResponse>>处理器集合
  3. 能解析出IEnumerable<IPipelineBehavior<TRequest, TResponse>>流水线行为
  4. 处理器按**瞬态(Transient)**生命周期注册

Microsoft 容器通过AddMediatR自动完成了以上全部(见 MediatRServiceCollectionExtensions.cs),而其他容器要么有"Microsoft DI 适配器"可借用,要么就得手动扫描注册。下文按接入难度从低到高排序。

二、7 大容器接入速查清单

容器接入方式是否借助 MS DI 适配器官方示例
Stashbox一行RegisterAssembliesProgram.cs
DryIocWithDependencyInjectionAdapter✅ 是Program.cs
LightInject按接口过滤扫描 +RegisterOrdered✅ 是Program.cs
SimpleInjectorRegisterAssemblyTypes+ 集合注册部分Program.cs
AutofacAsClosedTypesOf扫描 5 种开泛型✅ 是Program.cs
LamarConnectImplementationsToTypesClosing扫描Program.cs
Castle.WindsorBasedOn扫描 +CollectionResolverProgram.cs

下面逐个拆解关键代码。

三、内置基线:Microsoft DI 的一行AddMediatR

这是理解其他容器的基线。在 README.md 中可以看到,只需一行:

services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Startup>());

它会从指定程序集扫描并注册:IMediatorISenderIPublisher,以及IRequestHandler<,>INotificationHandler<>IStreamRequestHandler<>IRequestExceptionHandler<,,>IRequestExceptionAction<,>的全部实现,生命周期均为 transient。注意:流水线行为不会被自动扫描,需要用cfg.AddBehavior<>()等方法显式添加。

四、Stashbox 接入:代码最少的容器

Stashbox 内置了 MediatR 感知的程序集扫描规则,是整个 samples/MediatR.Examples.Stashbox/ 里代码最短的:

var container = new StashboxContainer() .RegisterAssemblies(new[] { typeof(Mediator).Assembly, typeof(Ping).Assembly }, serviceTypeSelector: Rules.ServiceRegistrationFilters.Interfaces); return container.GetRequiredService<IMediator>();

serviceTypeSelector: Rules.ServiceRegistrationFilters.Interfaces这一参数是关键——它会按接口注册实现类型,处理器集合和流水线行为都能被正确解析。

五、DryIoc 接入:借助 DI 适配器一行注册

DryIoc 官方提供 DryIoc.Microsoft.DependencyInjection 适配器,示例见 samples/MediatR.Examples.DryIoc/Program.cs:

container.RegisterMany(new[] { typeof(IMediator).GetAssembly(), typeof(Ping).GetAssembly() }, Registrator.Interfaces); var adapterContainer = container.WithDependencyInjectionAdapter(services); return adapterContainer.GetRequiredService<IMediator>();

⚠️一个专属坑点Mediator有多个构造函数,DryIoc 默认可能选不中你想要的那个。示例代码中给出了两种处理方式:要么加规则rules.With(FactoryMethod.ConstructorWithResolvableArguments),要么像示例那样显式指定构造函数参数(Made.Of(() => new Mediator(Arg.Of<IServiceProvider>())))。

六、LightInject 接入:接口过滤扫描 + 有序注册流水线

LightInject 的示例(samples/MediatR.Examples.LightInject/Program.cs)分三步:

  1. 扫描处理器RegisterAssembly时用过滤函数,只注册实现了IRequestHandler<,>INotificationHandler<>的类型;
  2. 注册流水线:用RegisterOrdered(typeof(IPipelineBehavior<,>), new[] { ... })显式声明行为的执行顺序(注意:MediatR 中后注册的行为先执行);
  3. 取适配器serviceContainer.CreateServiceProvider(services)得到IServiceProvider再解析IMediator

七、SimpleInjector 接入:注意开泛型处理器的特殊注册

SimpleInjector 示例(samples/MediatR.Examples.SimpleInjector/Program.cs)有两处值得注意:

  • container.Register(typeof(IRequestHandler<,>), assemblies)这类"按开泛型 + 程序集"的 API 扫描处理器;
  • 开泛型处理器必须显式纳入:默认的GetTypesToRegister不会注册开泛型定义(如ConstrainedPingedHandler<>),示例中通过IncludeGenericTypeDefinitions = true补齐,否则带泛型约束的处理器会"失踪";
  • 流水线用container.Collection.Register注册为集合。

八、Autofac 接入:AsClosedTypesOf 扫描 5 种处理器

Autofac 是最常被问到的容器,示例在 samples/MediatR.Examples.Autofac/Program.cs。核心套路:

  1. 定义 5 种 MediatR 开泛型接口数组(IRequestHandler<,>IRequestExceptionHandler<,,>IRequestExceptionAction<,>INotificationHandler<>IStreamRequestHandler<,>);
  2. 对每种接口用RegisterAssemblyTypes(...).AsClosedTypesOf(mediatrOpenType).AsImplementedInterfaces()扫描;
  3. builder.Populate(services)桥接 Microsoft DI,再用AutofacServiceProvider解析IMediator

示例代码里有两条实战提示值得留意:Autofac 返回最后注册的类型在前(影响流水线顺序),以及"一个类同时实现多种处理器接口会导致被调用两次"。

九、Lamar 接入:ConnectImplementationsToTypesClosing 自动接线

Lamar 的扫描 API 表达力很强,示例(samples/MediatR.Examples.Lamar/Program.cs)在一个cfg.Scan块里完成:

scanner.AssemblyContainingType<Ping>(); scanner.ConnectImplementationsToTypesClosing(typeof(IRequestHandler<,>)); scanner.ConnectImplementationsToTypesClosing(typeof(INotificationHandler<>)); // ... 以及另外两种异常处理器接口

随后用cfg.For(typeof(IPipelineBehavior<,>)).Add(...)逐条挂接异常处理、前后置处理器等流水线行为,并显式声明cfg.For<IMediator>().Use<Mediator>().Transient()。整体配置风格直观,适合团队中已有 .NET 经验的新手阅读。

十、Castle.Windsor 接入:CollectionResolver 与逆变过滤

Windsor 是清单中"机关"最多的容器(samples/MediatR.Examples.Windsor/Program.cs),三件必备的事:

  1. CollectionResolver子解析器:MediatR 依赖IEnumerable<T>集合解析,Windsor 默认不支持,必须AddSubResolver(new CollectionResolver(kernel))
  2. ContravariantFilter:见 ContravariantFilter.cs,用于让 MediatR 依赖的 C# 泛型逆变(如用IRequestHandler<IRequest, Unit>兼容更具体的请求)在 Windsor 里也能生效;
  3. 处理器扫描BasedOn(typeof(IRequestHandler<,>)).WithServiceAllInterfaces().AllowMultipleMatches(),注意AllowMultipleMatches()不能漏。

另外记得:Windsor 默认生命周期是Singleton,示例注释中特别提醒在 Web 场景下应改用PerWebRequest或 Transient 风格,避免IMediator被单例化带来的隐式共享状态问题。

十一、通用避坑清单:接入任何容器都检查一遍

  • 5 种处理器接口IRequestHandler<,>INotificationHandler<>IStreamRequestHandler<,>IRequestExceptionHandler<,,>IRequestExceptionAction<,>是否全部扫描注册?漏掉异常处理器,RequestExceptionHandler相关功能会静默失效;
  • 集合解析:容器是否支持IEnumerable<T>多实现解析(Windsor 需子解析器,SimpleInjector 用集合注册);
  • 流水线顺序:MediatR 中后注册的行为先执行,用"顺序注册"API(如 LightInject 的RegisterOrdered)时方向别搞反;
  • 生命周期IMediator与各处理器建议 transient(Lamar 示例中注释:"最多 container scoped");
  • 开泛型处理器:带泛型约束的处理器(开泛型定义)需要显式纳入注册(SimpleInjector 需IncludeGenericTypeDefinitions);
  • 构造选择Mediator有多个构造函数,非 Microsoft 容器建议显式指定(DryIoc 示例的做法)。

十二、怎么验证自己接对了?

每个容器示例都复用了同一个功能覆盖最全的运行器 Runner.cs(Autofac、Windsor、Stashbox 还开启了流式请求测试),它会实际发出 Ping/Pong 请求、通知、异常与流式请求,逐一检验处理器与流水线是否都按预期触发——你只需运行对应示例项目并对照控制台输出。

如果想看同一套"容器装配是否合规"的自动化断言,可以研究 test/MediatR.DependencyInjectionTests/ 目录:其中 BaseServiceProviderFixture.cs 定义了对 6 种容器统一的解析检查项(公共/私有/内部处理器能否被正确解析等),各容器只需实现一个 fixture 即可复用整套断言。

十三、选型小结

  • 新项目和 .NET 全家桶:直接用 Microsoft DI +AddMediatR,零额外代码;
  • 想用轻量容器:Stashbox 和 DryIoc 接入成本最低(几行代码 + 适配器);
  • 已有 Autofac/Lamar 存量项目:按本文的"开泛型扫描 + 集合注册"套路补一段注册代码即可,官方示例可整段参照;
  • 维护 Windsor 老系统:重点检查CollectionResolverContravariantFilter是否都已就位。

掌握"5 种处理器接口 + 流水线集合 + 生命周期"这个核心心智模型后,你会发现无论换成哪个容器,MediatR 的接入都只是换个 API 表达同一件事。

【免费下载链接】MediatRSimple, unambitious mediator implementation in .NET项目地址: https://gitcode.com/gh_mirrors/me/MediatR

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询