WinForm应用实战开发指南 - 如何实现类似事件总线的消息处理?

发布时间:2026/7/18 9:59:19

WinForm应用实战开发指南 - 如何实现类似事件总线的消息处理? MediatR是一款进程内的消息订阅、发布框架可实现请求/响应、命令、查询、通知和事件的消息传递解耦了消息处理器和消息之间耦合。提供了Send方法用于发布到单个处理程序、Publish方法发布到多个处理程序使用起来非常方便。目前支持 .NET Framework 、.NET Stardand、.NETCore等版本可跨平台使用。本文介绍在Winform系统开发中使用MediatR来实现类似事件总线的消息处理。PS给大家推荐一个C#开发可以用到的界面组件——DevExpress WinForms它能完美构建流畅、美观且易于使用的应用程序无论是Office风格的界面还是分析处理大批量的业务数据它都能轻松胜任DevExpress新旧版本帮助文档下载欢迎进QQ qun获取169725316安装使用MediatRMediatR的GitHub项目地址GitHub - jbogard/MediatR: Simple, unambitious mediator implementation in .NETMediatR的各种场景使用代码Home · jbogard/MediatR Wiki · GitHub如果我们在VS开发项目我们在Nugget上找到对应模块直接添加到项目引用即可如下所示。MediatR使用 Microsoft.Extensions.DependencyInjection.Abstractions 来 注入服务处理我们使用MediatR的时候首先需要构造ServiceCollection然后添加配置到其中。// IServiceCollection负责注册 IServiceCollection services new ServiceCollection(); //注册MediatR服务用于测试MediatR的服务 services.AddMediatR(cfg { cfg.RegisterServicesFromAssembly(typeof(Portal).Assembly); });使用注入服务的时候我们需要获得其中的ServiceProvider如下通过BuildServiceProvider 获得该对象。IServiceProvider provider services.BuildServiceProvider();然后我们创建一个静态类来存储这个对象。//存储全局IServiceProvider的接口实例, 便于后续获得接口实例 ServiceLocator.ConfigService(provider);其中静态类 ServiceLocator 的代码如下所示。/// summary /// 全局存储IServiceProvider /// /summary public class ServiceLocator { /// summary /// IOC中的IServiceProvider对象接口 /// /summary public static IServiceProvider SerivcePovider { get; private set; } /// summary /// 赋值IServiceProvider到静态变量中 /// /summary /// param nameproviderIServiceProvider对象接口/param public static void ConfigService(IServiceProvider provider) { SerivcePovider provider; } /// summary /// 获取指定服务接口实例 /// /summary /// returns/returns public static T GetServiceT() { return SerivcePovider.GetServiceT(); } }后面我们就可以通过该静态类的 GetServiceT() 方法获取对应的注入接口IMediator需要利用该接口来发送Send请求/应答命令或者发布Publish消息的处理。例如我们在窗体对象中定义该接口用于实际的相关命令、消息的处理。public partial class TestMediatR : BaseForm { private readonly IMediator _mediator; public TestMediatR() { InitializeComponent(); _mediator ServiceLocator.GetServiceIMediator(); }MediatR命令或者消息的处理MediatR是一个跨平台通过一种进程内消息传递机制进行请求/响应、命令、查询、通知和事件的消息传递并通过C#泛型来支持消息的智能调度其目的是消息发送和消息处理的解耦。它支持以单播和多播形式使用同步或异步的模式来发布消息创建和侦听事件。它主要的几个对象IMediator主要提供Send与Publish方法需要执行的命令都是通过这两个方法实现。IRequest命令查询 | 处理类所继承的接口一个有返回类型一个无返回类型一个查询对应一个处理类程序集只认第一个扫描到的类。IRequestHandler实现Handle方法 命令处理接口。命令查询 | 处理类继承它也可以继承AsyncRequestHandler实现抽象Handle方法、RequestHandler实现抽象Handle方法接口。INotification命令查询 | 处理类所继承的接口这个没有返回与IRequest不通的是可以对于多个处理类。INotificationHandler与IRequestHandler一样的只不过这是INotification的处理接口。Request/Response模式对象定义/// summary /// 请求类 /// /summary public class RetrieveInfoCommandRequest : IRequestRetrieveInfoCommandResponse { public string Text { get; set; } } /// summary /// 回应消息 /// /summary public class RetrieveInfoCommandResponse { public string OutputMessage { get; set; } } /// summary /// 请求应答处理类 /// /summary public class RetrieveInfoCommandHandler : IRequestHandlerRetrieveInfoCommandRequest, RetrieveInfoCommandResponse { public async TaskRetrieveInfoCommandResponse Handle(RetrieveInfoCommandRequest request, CancellationToken cancellationToken) { var response new RetrieveInfoCommandResponse(); response.OutputMessage $This is an example of MediatR using {request.Text}; return response; } }例如我们根据这个请求、应答的消息协议以及定义的处理Handler类唯一一个可以设计一个Winform界面来测试消息的处理。界面的代码如下所示。/// summary /// 测试MediatR的窗体例子 /// /summary public partial class TestMediatR : BaseForm { private readonly IMediator _mediator; public TestMediatR() { InitializeComponent(); _mediator ServiceLocator.GetServiceIMediator(); } /// summary /// 使用请求、应答的消息进行测试获得返回结果后输出显示 /// /summary private async void btnSend_Click(object sender, EventArgs e) { //应答处理 var outputMessage await _mediator.Send(new RetrieveInfoCommandRequest { Text this.txtSend.Text }); Console.WriteLine(outputMessage.OutputMessage); this.txtReceived.AppendText(outputMessage.OutputMessage Environment.NewLine); }上面的命令消息方式有返回值如果不需要返回值也可以采用这种一一应答的方式那么定义的时候继承IRequest接口即可。public class OneWay : IRequest { } public class OneWayHandler : IRequestHandlerOneWay { public Task Handle(OneWay request, CancellationToken cancellationToken) { // do work return Task.CompletedTask; } }Notification 消息通知模式如果我们需要类似事件多播的处理也就是常规的消息通知处理采用INotification方式。Notification模式将消息发布给多个处理程序消息的处理没有返回值。/// summary /// 通知类 /// /summary public class MyNotification : INotification { public string Message { get; } public MyNotification(string message) { Message message; } } /// summary /// Notification处理程序-模块1 /// /summary public class MyNotifyHandler : INotificationHandlerMyNotification { public Task Handle(MyNotification notification, CancellationToken cancellationToken) { var message 模块1-收到消息: notification.Message; //MessageDxUtil.ShowTips(message); //提示消息 var alert new AlertControl(); alert.FormLocation AlertFormLocation.TopRight; alert.AutoFormDelay 3000; alert.Show(Portal.gc.MainDialog, message, message); // 处理通知 Console.WriteLine($Notification处理程序-模块1-收到消息: {notification.Message}); return Task.CompletedTask; } } /// summary /// Notification处理程序-模块2 /// /summary public class MySecondNotifyHandler : INotificationHandlerMyNotification { public Task Handle(MyNotification notification, CancellationToken cancellationToken) { var message 模块2-收到消息: notification.Message; //MessageDxUtil.ShowTips(message); //提示消息 var alert new AlertControl(); alert.FormLocation AlertFormLocation.TopRight; alert.AutoFormDelay 3000; alert.Show(Portal.gc.MainDialog, message, message); // 处理通知 Console.WriteLine($Notification处理程序-模块2-收到消息: {notification.Message}); return Task.CompletedTask; } }我们在界面上发布消息的代码如下所示。private async void btnNotify_Click(object sender, EventArgs e) { //发布消息 await _mediator.Publish(new MyNotification(this.txtSend.Text)); }可以看到在控制台和UI上我们的都有测试消息的输出。默认情况下MediatR的消息发布是一个一个执行的即便是返回Task的情况也是使用await等待上一个执行完成后才进行下一个的调用。如果需要使用并行的方法进行调用可以进行定制具体可参考官方示例MediatR.Examples.PublishStrategies。对于MediatR来说无论是发送IRequest类型消息还是发布INotification类型消息都是异步的。这里需要特别留意即使你使用的是同步的消息处理程序对于消息发布来说都是异步的与你的处理程序是同步或异步无关。详细的介绍可以参考官方的案例介绍Home · jbogard/MediatR Wiki · GitHub。回顾WPF的MVVM的消息处理对于WPF其实也是类似采用该组件实现事件、消息的处理的不过如果我们采用MVVM的框架设计模式可以采用MVVM微软的CommunityToolkit.Mvvm的组件包的内置的消息处理模式。CommunityToolkit.Mvvm (又名 MVVM 工具包以前名为 Microsoft.Toolkit.Mvvm) 是一个现代、快速且模块化的 MVVM 库。官网介绍地址https://learn.microsoft.com/zh-cn/dotnet/communitytoolkit/mvvm/利用MVVM推送一条消息如下代码所示。//发送MVVM消息信息通知方式一 WeakReferenceMessenger.Default.Send(new ClickEventMessage(eventData));而其中 ClickEventMessage 是我们根据要求定义的一个消息对象类如下代码所示。完整的Command命令如下所示。/// summary /// 双击触发MVVM消息通知 /// /summary /// param nametypeName处理类型Number、Animal、WuHan/param /// returns/returns [RelayCommand] private async Task DoubleClick(string typeName) { var clickType ClickEventType.Number; var clickValue this.Number; ..............//处理不同typeName值逻辑//事件数据 var eventData new ClickEventData(clickType, clickValue); //发送MVVM消息信息通知方式一 WeakReferenceMessenger.Default.Send(new ClickEventMessage(eventData)); }通过这样的消息发送就需要有个地方来接收这个信息的我们在需要处理事件的父窗口中拦截处理消息即可。//处理MVVM的消息通知 WeakReferenceMessenger.Default.RegisterClickEventMessage(this, (r, m) { var data m.Value; var list ControlHelper.FindVisualChildrenLotteryItemControl(this.listControl); foreach (var lottery in list) { lottery.SetSelected(data); } });从而实现了WPF消息的发送和应答处理。本文转载自博客园 - 伍华聪

相关新闻