带有 ASP.NET Core DI 的 MediatR
Posted
技术标签:
【中文标题】带有 ASP.NET Core DI 的 MediatR【英文标题】:MediatR with ASP.NET Core DI 【发布时间】:2016-05-26 09:30:20 【问题描述】:我正在使用新的 ASP.NET Core,目前正在创建一个我想从 javascript 前端调用的 API。
我想使用中介者模式来减少耦合,我从 Jimmy Bogard 那里找到了 Library MediatR。
我的问题在于使用 DI 中的构建将其连接起来,我尝试查看 examples,但看不到它是如何绑定到启动类中的 ConfigureServices 方法的。
有人有什么见解吗?
更新:我通过我的 ConfigureService 方法让它工作了:
services.AddScoped<SingleInstanceFactory>(p => t => p.GetRequiredService(t));
services.Scan(scan => scan
.FromAssembliesOf(typeof(IMediator), typeof(MyHandler.Handler))
.AddClasses()
.AsImplementedInterfaces());
【问题讨论】:
github.com/jbogard/MediatR/blob/master/samples/… 对我来说似乎很简单,但是对于程序集扫描,您需要这个 Scrutor 包(ASP.NET Core 的 DI 不附带程序集扫描,并且没有计划发布它)跨度> 如何将它添加到 ConfigureService 方法中?services.AddTransient(typeof (IMediator), BuildMediator().GetType());
你不想那样注册它,Transient 意味着每次解决依赖关系时都会创建它。 services.AddScoped<SingleInstanceFactory>(p => t => p.GetRequiredService(t));
和 services.AddScoped<MultiInstanceFactory>(p => t => p.GetRequiredServices(t));
是工厂方法,它们被注入到调解器中并解决通知(多)或请求(单)
IMediator
本身可以注册为services.AddScoped<IMediator,Mediator>()
,因为它具有公共构造函数,并且代表已在上一步中注册。在示例中,最后一个是通过 Scrutor 扫描自动完成的
@Tseng 我自己的答案是否与您的答案相符?
【参考方案1】:
截至 2016 年 7 月,MediatR 的作者 Jimmy Bogard 已经发布了一个用于注册 MediatR 和 Handlers 的包,使用 ASP.Net Core DI 服务(实际上是接口IServiceCollection
,在Microsoft.Extensions.DependencyInjection
和不限于仅在 ASP.Net Core 中使用)。
MediatR.Extensions.Microsoft.DependencyInjection
Link to GitHub Project.
Link to NuGet Package information.
可以在here找到介绍该软件包及其功能的博客文章
直接从(非常短的)博文复制的注册示例:
public void ConfigureServices(IServiceCollection services)
services.AddMvc();
services.AddMediatR(typeof(Startup));
此包执行多项功能以启用 MediatR,包括扫描程序集以查找处理程序:
您可以传入处理程序所在的程序集,也可以从这些处理程序所在的程序集中传入 Type 对象。该扩展会将 IMediator 接口添加到您的服务、所有处理程序和正确的委托工厂以加载处理程序。然后在您的控制器中,您可以只使用 IMediator 依赖项:
public class HomeController : Controller
private readonly IMediator _mediator;
public HomeController(IMediator mediator)
_mediator = mediator;
public IActionResult Index()
var pong = _mediator.Send(new Ping Value = "Ping");
return View(pong);
【讨论】:
这应该是正确的答案。不仅更加优雅简洁,而且是Mediatr创作者推荐的一款。 嗯,这是 ***s 的政策,即“正确答案”是由提问者选择的解决他们特定问题的答案 - 在他们看来。正是通过投票,后来的答案或更广泛有用的答案才会引起人们的注意。然而,我确实希望人们在一个小时内停止回答他们自己的问题,并实际上给人们一个回答的机会。有许多不正确、较差或过时的答案,旁边带有绿色勾号;我建议人们阅读所有答案并确定适合他们的答案,并注意发布日期。 不幸的是,该库仅在处理程序是公共类时才有效。例如,如果使用内部范围可见性定义它不起作用 是的,也许您是 16 小时前在 GitHub 存储库上创建的关于内部范围界定的 GitHub 问题的作者。作者 Jimmy Bogard 通常很容易接受合理的功能要求,并解释了他的设计决定。问题链接:github.com/jbogard/…【参考方案2】:https://dotnetcoretutorials.com/ 提供了一个很好的教程。这是正确安装和配置 MediatR 的示例代码。
安装 MediatR
我们需要做的第一件事是安装 MediatR nuget 包。所以从你的包管理器控制台运行:
安装包MediatR
我们还需要安装一个包,它允许我们使用 .NET Core 中内置的 IOC 容器来发挥我们的优势(我们很快就会看到更多)。所以还要安装以下包:
安装包 MediatR.Extensions.Microsoft.DependencyInjection
最后我们打开我们的 startup.cs 文件。在我们的 ConfigureServices 方法中,我们需要添加一个调用来注册所有 MediatR 的依赖项。
public void ConfigureServices(IServiceCollection services)
services.AddMediatR(Assembly.GetExecutingAssembly());
//Other injected services.
这是链接:https://dotnetcoretutorials.com/2019/04/30/the-mediator-pattern-part-3-mediatr-library/
我希望这会有所帮助。
【讨论】:
【参考方案3】:我得到了它的工作,我的代码:
public void ConfigureServices(IServiceCollection services)
services.AddScoped<SingleInstanceFactory>(p => t => p.GetRequiredService(t));
services.AddScoped<MultiInstanceFactory>(p => t => p.GetRequiredServices(t));
services.Scan(scan => scan
.FromAssembliesOf(typeof(IMediator), typeof(MyHandlerOne.Handler))
.FromAssembliesOf(typeof(IMediator), typeof(MyHandlerTwo.Handler))
.AddClasses()
.AsImplementedInterfaces());
我有一个实现 MultiInstanceFactory 需要的 GetRequiredService 的类:
public static class GetServices
public static IEnumerable<object> GetRequiredServices(this IServiceProvider provider, Type serviceType)
return (IEnumerable<object>)provider.GetRequiredService(typeof(IEnumerable<>).MakeGenericType(serviceType));
【讨论】:
【参考方案4】:我创建了一个DI helper for ASP.NET Core RC2,您可以将其添加到您的创业公司。它为您提供了基于基本约定的映射,因此如果您有这样的类:
MyClass : IMyClass
它将在 IOC 容器中映射 IMyClass
,使其可用于注入。
我还添加了 MediatR 的映射。
使用它只需将该类添加到您的项目中,然后在您的 startup.cs 类中添加您需要的行到 ConfigureServices()
方法:
public void ConfigureServices(IServiceCollection services)
//Other Code here......
var ioc = new PearIoc(services);
//ioc.AddTransient<IEmailSender, AuthMessageSender>();
//ioc.AddTransient<ISmsSender, AuthMessageSender>();
ioc.WithStandardConvention();
ioc.WithMediatR();
ioc.RunConfigurations();
我添加AddTransient()
方法只是为了方便(您也可以只使用services.AddTransient()
),但它也公开了IServiceCollection
,以防您需要使用它做更多事情。
您也可以像我对 .WithMediatR()
扩展所做的那样对其进行扩展,并编写您自己的自定义映射。
【讨论】:
【参考方案5】:根据 MediatR 文档注册 MediatR 服务和所有处理程序,您应该以这种方式使用 AddMediatR 方法:
public void ConfigureServices(IServiceCollection services)
services.AddMvc();
services.AddMediatR(typeof(Startup));
这很简单,很舒服,但是如果您想更换其中一个处理程序怎么办? 然后你应该找到 oldhandler.cs 并从中删除接口,这样一个以上的实现就不会有 ID 冲突。
为避免这种情况,我的建议是手动注册每个处理程序
public void ConfigureServices(IServiceCollection services)
services.AddMvc();
services.AddMediatR(typeof(Mediator)); //registering MediatR and all required dependencies
//registering handlers
services.AddScoped<IRequestHandler<CreateProductCommand, int>,CreateProductCommandHandler>();
services.AddScoped<IRequestHandler<DeleteProductCommand, int>,DeleteProductCommandHandler>();
此解决方案允许您为同一命令拥有多个处理程序实现,并控制使用女巫的实现
【讨论】:
以上是关于带有 ASP.NET Core DI 的 MediatR的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)