【问题标题】:MediatR with ASP.NET Core DI带有 ASP.NET Core DI 的 MediatR
【发布时间】: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&lt;SingleInstanceFactory&gt;(p =&gt; t =&gt; p.GetRequiredService(t));services.AddScoped&lt;MultiInstanceFactory&gt;(p =&gt; t =&gt; p.GetRequiredServices(t)); 是工厂方法,它们被注入到调解器中并解决通知(多)或请求(单)
  • IMediator 本身可以注册为services.AddScoped&lt;IMediator,Mediator&gt;(),因为它具有公共构造函数,并且代表已在上一步中注册。在示例中,最后一个是通过 Scrutor 扫描自动完成的
  • @Tseng 我自己的答案是否与您的答案相符?

标签: c# asp.net asp.net-core mediatr


【解决方案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创作者推荐的一款。
  • 嗯,这是 StackOverflows 的政策,即“正确答案”是由提问者选择的解决他们特定问题的答案 - 在他们看来。正是通过投票,后来的答案或更广泛有用的答案才会引起人们的注意。然而,我确实希望人们在一个小时内停止回答他们自己的问题,并实际上给人们一个回答的机会。有许多不正确、较差或过时的答案,旁边带有绿色勾号;我建议人们阅读所有答案并确定适合他们的答案,并注意发布日期。
  • 不幸的是,该库仅在处理程序是公共类时才有效。例如,如果使用内部范围可见性定义它不起作用
  • 是的,也许您是 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>();     
        
            }
        

        此解决方案允许您为同一命令拥有多个处理程序实现,并控制使用女巫的实现

        【讨论】:

          猜你喜欢
          • 2020-01-23
          • 1970-01-01
          • 2023-04-03
          • 2017-08-03
          • 2017-07-28
          • 2020-06-09
          • 2021-04-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多