【问题标题】:Integrate Mediatr with Autofac将 Mediatr 与 Autofac 集成
【发布时间】:2017-03-16 15:06:42
【问题描述】:

我使用的是 .NET Core(注意:不是 Web 环境)。我需要集成 MediatR 和 Autofac。

wiki has a guide 和 StructureMap 示例。另外,我已经简化了Autofac sample。没有提到生命周期范围,但是在a separate project 中,我找到了有用的 cmets 并将它们转换为 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()
  • 根据请求的前/后处理器,即InstancePerLifetimeScope()
  • 行为为瞬态,即InstancePerDependency()

例如

builder.RegisterType<EditCommandHandler>().AsImplementedInterfaces().InstancePerDependency();

但是,在我见过的大多数代码示例中,尤其是对于 StructureMap,还有大量其他注册(例如 IRequestHandler&lt;,&gt;IRequestHandler&lt;&gt;IAsyncRequestHandler&lt;,&gt;IAsyncRequestHandler&lt;&gt;ICancellableAsyncRequestHandler&lt;,&gt;ICancellableAsyncRequestHandler&lt;&gt;INotificationHandler&lt;&gt;IAsyncNotificationHandler&lt;&gt;ICancellableAsyncNotificationHandler&lt;&gt;) 和ASP.NET Core container's 集成也非常复杂。我没有做过类似的事情。

如果你有这个在生产中工作,你的配置与我的相比如何?谢谢!

【问题讨论】:

    标签: .net .net-core autofac mediatr


    【解决方案1】:

    TL;DR;

    我认为你的注册很好。


    告诉我更多信息 - 也就是让我们一一解答您的问题

    您当前的注册

    MediatR 需要您注册 SingleInstanceFactoryMultiInstanceFactory,因为 Mediator 课程需要它们。

    然后你需要注册你的处理程序和行为,你这样做,所以你很好。

    我可以做的一个评论是,看看您的示例,您似乎一个接一个地注册了您的处理程序。虽然这可行 - 这是最重要的,但这意味着每次添加新的请求/处理程序对时,都必须在 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&lt;TRequest&gt; 的不返回值,而具有two generic parameters like IRequestHandler&lt;TRequest, TResponse&gt; 的则返回值。但是您的注册将取决于您是否使用它们。

    ASP.NET Core 集成部分

    您使用 Autofac,所以不用担心。如果您使用 ASP.NET Core DI 容器,该包旨在帮助您为您注册处理程序。这当然很复杂,因为它会进行汇编扫描以查找代码中的所有处理程序并为您注册它们。但同样,您无需担心,因为您使用的是另一个容器。

    【讨论】:

    • 很棒的答案,像往常一样 Mickaël,谢谢!我只需要与在生产中使用 Autofac 的人确认一下,因为 Jimmy 似乎使用的是 StructureMap,所以示例/示例都是为了这个。
    • 顺便说一句,你知道为什么单/多代表注册有var ctx = context.Resolve&lt;IComponentContext&gt;()吗? context 解析为同一件事似乎没有必要,但如果您排除它,则它无法解析。
    • 我知道你必须这样做,因为你的注册中有一个 lambda 表达式 (t =&gt; { object o; return ctx.TryResolve(t, out o) ? o : null; };),并且无法捕获 Register 方法中提供的原始 IComponentContext 实例。虽然它解析为相同的type,但我相信它不会解析为相同的instance。但很遗憾,我无法提供更详细的解释。
    • 我也是这么想的(这是一个关闭问题),所以我为他们俩记录了.GetHashCode(),他们是一样的。所以它似乎没有必要,但如果你删除它就会失败。奇怪,但我并不在乎,因为它有效。
    • 在我的代码中,我在任何地方都看不到中介服务的范围,例如命令和处理程序。如果我只有 AsClosedTypesOf 和 A​​sIMplementedInterfaces ,我如何检查创建的范围是什么?
    【解决方案2】:

    对于任何发现此帖子的人:我创建了一个 nuget-package 作为 AutoFac 的 ContainerBuilder 的扩展。

    我知道有一个基于 Microsofts-DI,但我的与 AutoFac 完全集成,并且与 ASP.NET-Core 完美结合。

    您需要做的就是调用容器构建器上的扩展方法并传入一个或多个程序集。

    builder.AddMediatR(typeof(Startup).Assembly);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-25
      • 2015-02-10
      • 2014-08-15
      • 2017-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多