为什么我不需要调用 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
相关类型 - 例如命令和通知处理程序 - 触发不止一次。
确保每个程序集只调用一次。
我有一个同时使用 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
相关类型 - 例如命令和通知处理程序 - 触发不止一次。
确保每个程序集只调用一次。