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

发布于 2025-01-12 03:03:34 字数 2993 浏览 0 评论 0原文

我有一个同时使用 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 发布事件时,它会发布相同的事件三次。所以然后我注释掉了MediatorModule中的JobSeekerRegisteredDomainEventRelayHandler注册。一旦我这样做了,它就只发布了该事件两次。

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

所以现在我真的很困惑 - 为什么 Mediatr 仍然有效,即使我注释掉了 AddMediatr()?为什么在未评论的情况下将事件发布两次?

I have an Web API application that uses both Mediatr and Autofac.

In my Startup.ConfigureServices method I have:

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

    services.AddMediatR(executingAssembly);
}

In my Startup.ConfigureContainer() I have:

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

In my MediatorModule based on Autofac I have:

    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; };
    });
}

And my ApplicationModule is:

    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();
    }

When I do the above and publish an event using Mediatr, it publishes the same event three times. So then I commented out the JobSeekerRegisteredDomainEventRelayHandler registration in MediatorModule. Once I did this then it only published the event twice.

I then commented out services.AddMediatr() and everything worked correctly - the event only got published once.

So now I am really confused - why does Mediatr still work even though I commented out AddMediatr()? Why did it publish the event twice when it is uncommented?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼泪淡了忧伤 2025-01-19 03:03:34

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

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

Mediatr GitHub wiki 提供了以下情况下要遵循的步骤:使用Autofac
还有一个完整的 示例使用上面的代码来注册IMediatr

该 wiki 显示您应该使用 AddMediatr 如果您使用 ASP.NET Core DI 容器,但你不是。


您还多次调用 Autofacs RegisterAssemblyTypes 方法,该方法是 扫描一个,这意味着它会注册相应程序集中的所有类型。
当您对同一程序集多次执行此操作时,其 IMediatr 相关类型(例如命令和通知处理程序)会多次触发。
确保每个程序集仅调用一次。

IMediatr is still available because you (also) register it via below call in your code.

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

The Mediatr GitHub wiki provides the steps to follow when e.g. using Autofac.
There's also a full example which is using the code above to register IMediatr.

That wiki shows you should make use of AddMediatr in case you're using the ASP.NET Core DI container, which you are not.


You are also making multiple calls to Autofacs RegisterAssemblyTypes method, which is a scanning one, meaning it registers all types in the corresponding assembly.
When you do that more than once for the same assembly, its IMediatr related types - e.g. command and notification handlers - fire more than once.
Make sure to make that call only once per assembly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文