WPF中使用路由模式处理Mqtt消息 直接上代码特征[AttributeUsage(AttributeTargets.Method,AllowMultipletrue,Inheritedfalse)]publicclassMqttTopicAttribute:Attribute{publicstringTopic{get;}/// summary/// 描述可选用于日志/文档/// /summarypublicstringDescription{get;set;};publicMqttTopicAttribute(stringtopic){if(string.IsNullOrWhiteSpace(topic))thrownewArgumentException(Topic 不能为空,nameof(topic));Topictopic;}}注册路由/// summary/// 路由注册/// /summarypublicclassMqttRouteRegistry{publicDictionarystring,List(Type ServiceType,MethodInfo Method)Routes{get;}new(StringComparer.OrdinalIgnoreCase);publicvoidScanAssembly(Assemblyassembly){foreach(vartypeinassembly.GetTypes()){varmethodstype.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);foreach(varmethodinmethods){//使用 GetCustomAttributes 获取方法上贴的所有 MqttTopic 特性varattributesmethod.GetCustomAttributesMqttTopicAttribute();foreach(varattributeinattributes){// 验证方法签名必须包含且仅包含一个 stringvarparametersmethod.GetParameters();// 校验参数类型是否为 MqttMessageContextif(parameters.Length!1||parameters[0].ParameterType!typeof(MqttMessageContext)){thrownewInvalidOperationException($[MqttTopic] 方法{type.Name}.{method.Name}必须有且仅有一个 MqttMessageContext 参数);}// 验证返回值if(method.ReturnType!typeof(Task)method.ReturnType!typeof(void)){thrownewInvalidOperationException($[MqttTopic] 方法{type.Name}.{method.Name}返回值必须是 void 或 Task);}// 初始化或追加到列表if(!Routes.TryGetValue(attribute.Topic,outvarhandlerList)){handlerListnewList(Type,MethodInfo)();Routes[attribute.Topic]handlerList;}handlerList.Add((type,method));}}}}}路由分发publicrecordMqttMessageContext(stringtopic,stringpayload);/// summary/// 路由分发/// /summarypublicclassMqttMessageDispatcher{privatereadonlyMqttRouteRegistry_registry;privatereadonlyIServiceProvider_serviceProvider;publicMqttMessageDispatcher(MqttRouteRegistryregistry,IServiceProviderserviceProvider){_registryregistry;_serviceProviderserviceProvider;}publicasyncTaskDispatchMessageAsync(stringtopic,stringpayload){// 1. 如果没有任何类订阅这个 Topic直接退出if(!_registry.Routes.TryGetValue(topic,outvarhandlers)||handlers.Count0){return;}// 2. 创建一个顶层的作用域或者为每个订阅者创建独立作用域。// 这里推荐采用“一个 Topic 创建一个 Scope”如果追求极致隔离也可以在 foreach 内部单独 Scope。using(varscope_serviceProvider.CreateScope()){vartasksnewListTask();// 3. 遍历所有订阅了该 Topic 的处理器实现一对多广播foreach(varhandlerinhandlers){// 使用 Task.Run 进行并行多线程分发防止订阅者 A 耗时导致订阅者 B 延迟收到消息tasks.Add(Task.Run(async(){try{// 动态向 DI 容器请求实例例如 MainWindowViewModel、AlarmService 等varinstancescope.ServiceProvider.GetService(handler.ServiceType);if(instancenull)return;varcontextnewMqttMessageContext(topic,payload);// 执行方法if(handler.Method.ReturnTypetypeof(Task)){await(Task)handler.Method.Invoke(instance,newobject[]{context});}else{handler.Method.Invoke(instance,newobject[]{context});}}catch(Exceptionex){// 单个订阅者执行崩溃捕获它不影响其他类接收消息System.Diagnostics.Debug.WriteLine($[Dispatcher] 订阅者{handler.ServiceType.Name}处理失败:{ex.Message});}}));}// 等待当前 Topic 的所有订阅者全部处理完毕awaitTask.WhenAll(tasks);}}}依赖注入// 1. 初始化并注册 MQTT 路由注册表,所有消息处理的类必须注入varregistrynewMqttRouteRegistry();// 扫描当前程序集包含所有 ViewModel 和 Serviceregistry.ScanAssembly(Assembly.GetExecutingAssembly());services.AddSingleton(registry);services.AddSingletonMqttMessageDispatcher();//所有包含 [MqttTopic] 特性的类必须注册到容器中services.AddSingletonMainWindowViewModel();调用[MqttTopic(PLC01/DB7000.58.1)] private async Task UpdateMode(MqttMessageContext context) { Console.WriteLine($收到消息{context.payload}); }

相关新闻

最新新闻

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 本文以 getopt(3) 手册 为核心&a…

2026/9/23 4:54:42
轻量服务器还是ECS?大促云服务器选购与避坑实战指南

轻量服务器还是ECS?大促云服务器选购与避坑实战指南

每年大促节点,群里永远有人在问同一个问题:“38元的轻量服务器到底怎么抢?为什么我每次点进去都是已售罄?68元直购和99元的ECS我到底选哪个?”作为一个常年帮团队和自己采购云服务器的老用户,我太清楚这种纠…

2026/9/23 8:01:55
为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目地址:…

2026/9/23 8:02:11
PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署 【免费下载链接】PaddleOCR Turn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between i…

2026/9/23 8:01:38
Spring源码解析:构造器注入的类型转换与候选匹配机制

Spring源码解析:构造器注入的类型转换与候选匹配机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/23 8:01:21
openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由 【免费下载链接】openai-agents-python A lightweight, powerful framework for multi-agent workflows 项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-pyth…

2026/9/23 8:02:28

日新闻

周新闻