为什么我不需要调用 services.AddMediatr()?

Why dont I need to call services.AddMediatr()?

我有一个同时使用 Mediatr 和 Autofac 的 Web API 应用程序。

在我的 Startup.ConfigureServices 方法中我有:

void ConfigureServices(IServiceCollection services)
{
    var executingAssembly = Assembly.GetExecutingAssembly();

    services.AddMediatR(executingAssembly);
}

在我的 Startup.ConfigureContainer() 中我有:

        builder.RegisterModule(new MediatorModule());
        builder.RegisterModule(new ApplicationModule("Connection String"));

在我基于 Autofac 的 MediatorModule 中,我有:

    protected override void Load(ContainerBuilder builder)
{
    Guard.Against.Null(builder, nameof(builder));

    builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly)
        .AsImplementedInterfaces();

    // Register Repository class
    builder.RegisterAssemblyTypes(typeof(IJobSeekerRepository<JobSeeker>).GetTypeInfo().Assembly)
        .AsImplementedInterfaces();

    // Register Event Service
    builder.RegisterAssemblyTypes(typeof(IJobSeekerMgmtEventService).GetTypeInfo().Assembly)
            .AsImplementedInterfaces();

    // Commands Handlers
    builder.RegisterAssemblyTypes(typeof(AddCreditCardCommand).GetTypeInfo().Assembly)
        .AsClosedTypesOf(typeof(IRequestHandler<,>));

    // Domain Events 

builder.RegisterAssemblyTypes(typeof(JobSeekerRegisteredDomainEventRelayHandler).GetTypeInfo().Assembly)
        .AsClosedTypesOf(typeof(INotificationHandler<>));

    // Register Service Factory
    builder.Register<ServiceFactory>(context =>
    {
        var componentContext = context.Resolve<IComponentContext>();
        return t => { return componentContext.TryResolve(t, out var o) ? o : null; };
    });
}

我的 ApplicationModule 是:

    protected override void Load(ContainerBuilder builder)
    {
       builder.RegisterType(typeof(JobSeekerRepository<JobSeeker>))
        .As(typeof(IJobSeekerRepository<JobSeeker>))
        .InstancePerLifetimeScope();

       builder.RegisterType<RequestManager>()
         .As<IRequestManager>()
         .InstancePerLifetimeScope();

       builder.RegisterType<JobSeekerContextSeed>().InstancePerLifetimeScope();

       builder.RegisterType(typeof(JobSeekerMgmtEventService))
          .As(typeof(IJobSeekerMgmtEventService))
          .InstancePerLifetimeScope();

       // AddCreditCardCommand
       builder.RegisterType(typeof(IdentifiedCommandHandler<AddCreditCardCommand, CreditCardModel>))
              .As<IRequestHandler<IdentifiedCommand<AddCreditCardCommand, CreditCardModel>, CreditCardModel>>()
              .AsImplementedInterfaces();
    }

当我执行上述操作并使用 Mediatr 发布事件时,它会发布同一个事件 3 次。所以后来我注释掉了MediatorModule中的JobSeekerRegisteredDomainEventRelayHandler注册。一旦我这样做了,它只发布了两次事件。

然后我注释掉了 services.AddMediatr() 并且一切正常 - 该事件只发布了一次。

所以现在我真的很困惑 - 为什么即使我注释掉了 AddMediatr() Mediatr 仍然有效?为什么取消评论的时候发布了两次?

IMediatr 仍然可用,因为您(也)通过代码中的以下调用注册了它。

builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly)
    .AsImplementedInterfaces();

Mediatr GitHub wiki 提供了以下步骤使用 Autofac.
还有一个完整的example,它使用上面的代码来注册IMediatr

该 wiki 显示您应该使用 AddMediatr,以防您使用 ASP.NET Core DI container,而您没有。


您还多次调用了 Autofacs RegisterAssemblyTypes 方法,这是一个 scanning 方法,这意味着它会在相应的程序集中注册所有类型。
当您对同一个程序集执行多次时,它的 IMediatr 相关类型 - 例如命令和通知处理程序 - 触发不止一次。 确保每个程序集只调用一次。