c# - 处理程序多次触发同一通知,但自动接线按预期工作
问题描述
我有带有 StructureMap 和 Mediatr 的 ASP.NET Core 3.1。
以前,当我使用默认 DI 容器时,我会让我的子处理程序触发两次。那里的功能非常有限,所以我切换到了 StructureMap。但是,当我对扫描仪应用不同的设置时,我无法获得预期的行为。它是执行两次的基处理程序或子处理程序,或两者兼而有之。唯一可行的情况是,我没有为 指定任何内容typeof(INotificationHandler<>)
,由于自动接线(可能?),一切正常,但我觉得通知处理程序调用之间存在延迟,所以我想在应用程序上正确配置容器启动。
我的通知和通知处理程序如下。预期行为:发布子通知时,触发两个处理程序一次
public class ApplicationUserRegisteredNotification : INotification
{
public ApplicationUser User { get; }
public ApplicationUserRegisteredNotification(ApplicationUser user)
{
User = user;
}
}
public class SpecificUserRegisteredNotification : ApplicationUserRegisteredNotification
{
public SpecificUserProfile SpecificUser { get; }
public SpecificUserRegisteredNotification(SpecificUserProfile specificUser)
: base(specificUser.User)
{
SpecificUser = specificUser;
}
}
public class SendEmailConfirmationEmail : INotificationHandler<ApplicationUserRegisteredNotification>
{
// some code
}
public class SendAdminVerifySpecificUserRegistration : INotificationHandler<SpecificUserRegisteredNotification>
{
// some code
}
我StructureMap.AspNetCore
用来生产IServiceProvider
,我可以使用什么选项来明确应用自动布线逻辑?在下面的评论中,您可以看到每个选项的输出。
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// some code
var container = new Container(cfg =>
{
cfg.Scan(scanner =>
{
scanner.AssemblyContainingType(GetType());
scanner.ConnectImplementationsToTypesClosing(typeof(IRequestHandler<>));
scanner.ConnectImplementationsToTypesClosing(typeof(IRequestHandler<,>));
//scanner.ConnectImplementationsToTypesClosing(typeof(INotificationHandler<>)); // both handlers triggered twice in given sequence: base, child, base, child
//scanner.AddAllTypesOf(typeof(INotificationHandler<>)); // both handlers triggered in given sequence: base, base, child
// nothing: everything works as expected - base, child, but switching between handlers is rather slow
});
});
container.Populate(services);
return container.GetInstance<IServiceProvider>();
}
程序.cs
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStructureMap()
.UseStartup<Startup>();
}
在 StructureMap 之前,我的配置看起来像这样
services.AddTransient<INotificationHandler<SpecificUserRegisteredNotification>, SendEmailConfirmationEmail>();
services.AddTransient<INotificationHandler<OtherSpecificUserRegisteredNotification>, SendEmailConfirmationEmail>();
services.AddTransient<IRequestHandler<RegisterSpecificCommand, BaseCommandResponse>, RegisterApplicationUserCommandHandler>();
services.AddTransient<IRequestHandler<RegisterOtherSpecificCommand, BaseCommandResponse>, RegisterApplicationUserCommandHandler>();
解决方案
利用:
services.AddMediatR(AppDomain.CurrentDomain.Load("AssemblyName"));
正常注册您的处理程序。例子:
services.AddTransient<INotificationHandler<SpecificUserRegisteredNotification>, SendEmailConfirmationEmail>();
推荐阅读
- django - 如何更新 Django formset 中多个实例的外键
- java - 如何通过 Java 使用 Selenium 在 Instagram 中定位带有文本 Not Now 的元素
- r - 从数据框在 R 中创建嵌套的键/值对
- python - plotly.express 上的常量 AttributeError
- python - 有没有办法将多个图像保存到 python 中的数组以供以后使用?
- amazon-web-services - 在运行 AWS Glue ETL 作业并命名输出文件名时,有没有办法从 S3 存储桶中读取文件名。pyspark 是否提供了一种方法来做到这一点?
- python - 如何对用户输入使用尝试和错误,如果错误不会删除python中的文本文件内容?
- javascript - jQuery实时刷新,无需等待焦点改变
- c - 我需要在 C 中释放 strerror() 的结果吗?
- javascript - Cytoscape.js - 为什么以编程方式添加新实例时旧图/实例会消失?