C# 基于 Windows 系统与 Visual Studio 2017 的 Messenger 消息传递机制详解:发布-订阅模式实现

在这里插入图片描述

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用,熟悉DICOM医学影像及DICOM协议,业余时间自学JavaScript,Vue,qt,python等,具备多种混合语言开发能力。撰写博客分享知识,致力于帮助编程爱好者共同进步。欢迎关注、交流及合作,提供技术支持与解决方案。\n技术合作请加本人wx(注明来自csdn):xt20160813

在这里插入图片描述

C# 基于 Windows 系统与 Visual Studio 2017 的 Messenger 消息传递机制详解:发布-订阅模式实现

在 C# 开发中,特别是在 Windows 平台的客户端应用程序开发中,Messenger 是一种基于发布-订阅模式(Publish-Subscribe Pattern)的消息传递机制,广泛应用于 MVVM(Model-View-ViewModel)架构,如 WPF 应用程序。它通过 Messenger.Default.SendMessenger.Default.Register 实现松耦合的模块间通信,特别适合复杂 UI 交互和跨组件协作场景。本文基于 Windows 系统Visual Studio 2017,结合历史对话中提到的代码示例(如 Messenger.Default.Send<string>("Recovery", "fanxuan")),详细解析 Messenger 的实现原理、配置环境、应用场景及完整代码示例,确保内容准确、具体且可直接应用于 Windows 开发。


一、引言

在 Windows 平台的 C# 开发中,MVVM 架构常用于构建可维护、可测试的应用程序。Messenger 作为 MVVM 框架(如 MVVM Light、Prism)的核心组件,通过发布-订阅模式实现模块间通信,避免直接耦合。历史对话中的代码展示了 Messenger 在医学影像系统(DICOM 相关)中用于触发恢复按钮状态的场景,例如通过 ESC 键发送 "Recovery" 消息。本文将从 Windows 系统和 Visual Studio 2017 的开发环境出发,深入剖析 Messenger 的工作机制,提供配置指南、完整代码示例,并结合实际应用场景(如 UI 状态恢复)进行说明。


二、发布-订阅模式与 Messenger 概述

1. 发布-订阅模式

发布-订阅模式是一种解耦设计模式,核心组件包括:

  • 发布者(Publisher):发送消息,不关心接收者。
  • 订阅者(Subscriber):注册对特定消息的兴趣,处理接收到的消息。
  • 消息中介(Broker):管理消息分发,通过消息类型或令牌(Token)过滤。

优点

  • 松耦合:模块间无需直接引用,降低依赖。
  • 一对多通信:支持多个订阅者处理同一消息。
  • 线程安全:结合 Windows 的 Dispatcher 机制,确保 UI 操作在主线程执行。
2. Messenger 的功能

Messenger 是 MVVM 框架(如 MVVM Light)提供的消息传递工具,核心方法包括:

  • 发送消息Messenger.Default.Send<T>(message, token),发送类型为 T 的消息,可指定令牌 token
  • 注册订阅Messenger.Default.Register<T>(recipient, token, action),注册处理特定类型和令牌的消息。
  • 令牌机制:通过 token(如字符串 "fanxuan")实现定向消息传递。
  • 线程支持:结合 WPF 的 Dispatcher 确保线程安全。

在历史对话中,Messenger.Default.Send<string>("Recovery", "fanxuan") 用于发送恢复命令,目标是注册了 "fanxuan" 令牌的订阅者,通常用于 UI 状态重置或 DICOM 数据操作。


三、Windows 系统与 Visual Studio 2017 环境配置

1. 系统与工具要求
  • 操作系统:Windows 10(推荐 64 位,支持 Visual Studio 2017)。
  • 开发工具:Visual Studio 2017(Community、Professional 或 Enterprise 版本)。
  • 框架:.NET Framework 4.6.1 或更高版本(WPF 项目常用)。
  • NuGet 包:MVVM Light(MvvmLightLibs)。
2. 配置 MVVM Light

在 Visual Studio 2017 中安装 MVVM Light:

  1. 打开 NuGet 包管理器
    • 在 Visual Studio 2017 中,点击 工具 > NuGet 包管理器 > 管理解决方案的 NuGet 包
  2. 搜索并安装 MVVM Light
    • 搜索 MvvmLightLibs,选择 GalaSoft.MvvmLight,点击 安装
    • 安装完成后,项目引用中将包含 GalaSoft.MvvmLight.dll
  3. 验证环境
    • 创建一个 WPF 项目,添加以下 using 语句:
      using GalaSoft.MvvmLight;
      using GalaSoft.MvvmLight.Messaging;
      
    • 确保无编译错误。
3. 项目设置
  • 创建 WPF 项目
    • 在 Visual Studio 2017 中,选择 文件 > 新建 > 项目 > Visual C# > Windows 经典桌面 > WPF 应用
    • 项目命名为 MessengerDemo
  • 添加 ViewModel
    • 创建 ViewModels 文件夹,添加 MainViewModel.csButtonViewModel.cs
  • 配置 Dispatcher
    • WPF 项目默认包含 Dispatcher,无需额外配置。若需自定义 Dispatcher,可使用 Application.Current.Dispatcher

四、Messenger 的核心方法

1. Messenger.Default.Send

签名

void Send<T>(T message, object token = null);
  • 参数
    • message:消息内容(如字符串 "Recovery")。
    • token:可选的令牌,用于过滤接收者(如 "fanxuan")。
  • 作用:将消息广播给匹配 token 和类型 T 的订阅者。
  • 示例
    Messenger.Default.Send<string>("Recovery", "fanxuan");
    
2. Messenger.Default.Register

签名

void Register<T>(object recipient, object token, Action<T> action);
  • 参数
    • recipient:订阅者对象(通常为 this)。
    • token:与发送端匹配的令牌。
    • action:收到消息后的回调函数。
  • 作用:注册处理特定类型和令牌的消息。
  • 示例
    Messenger.Default.Register<string>(this,"fanxuan",message => { /* 处理逻辑 */ }
    );
    
3. 消息传递流程
graph LRA[Send: Messenger.Default.Send<string>("Recovery", "fanxuan")] --> B[Messenger 中介]B --> C[查找匹配 "fanxuan" 和 string 的订阅者]C --> D[Register: Messenger.Default.Register<string>(this, "fanxuan", ...)]D --> E[执行回调: Dispatcher.Invoke(button1_Click)]

五、Messenger 实现原理

Messenger 基于单例模式(Messenger.Default),内部维护订阅者列表。核心逻辑包括:

  1. 订阅管理
    • Register 方法将 {recipient, token, action} 存储在字典中,键为消息类型 Ttoken
  2. 消息分发
    • Send 方法遍历订阅者列表,匹配 Ttoken,调用对应的 action
  3. 线程安全
    • 在 WPF 中,Dispatcher.Invoke 确保 UI 操作在主线程执行。
  4. 令牌匹配
    • 令牌通过 Equals 方法比较(如字符串的哈希比较),实现高效过滤。

六、Messenger 在历史对话中的应用

历史对话中的代码展示了 Messenger 在医学影像系统中的应用,用于触发 UI 恢复:

发送端
case ItCallBackMSG.Recovery: // 通过 ESC 键触发恢复
{Messenger.Default.Send<string>("Recovery", "fanxuan");break;
}
  • 场景:用户按 ESC 键触发 ItCallBackMSG.Recovery,发送 "Recovery" 消息到 "fanxuan" 通道。
  • 目的:通知订阅者执行 UI 按钮状态恢复或 DICOM 数据重置。
接收端
Messenger.Default.Register<string>(this,"fanxuan",message => DcmOperateDispatcher.Invoke(new Onclick(button1_Click), null, null)
);
  • 场景:某个类(可能是 ViewModel 或 View)注册 "fanxuan" 通道,收到消息后调用 button1_Click
  • 线程安全DcmOperateDispatcher.Invoke 确保回调在 UI 线程执行。
  • 改进建议:添加消息内容判断(如 if (message == "Recovery"))以提高特异性。

七、完整代码示例

以下是一个基于 WPF 的完整示例,展示 Messenger 在 Windows 系统中的应用,模拟 ESC 键触发按钮状态恢复。

1. 项目结构
  • MainWindow.xaml:主窗口,包含一个按钮。
  • MainViewModel.cs:发送恢复消息。
  • ButtonViewModel.cs:接收消息并处理按钮状态。
2. XAML(MainWindow.xaml)
<Window x:Class="MessengerDemo.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="Messenger Demo" Height="200" Width="300"><Grid><Button Content="Recover State" Width="100" Height="30"Command="{Binding RecoverCommand}"/></Grid>
</Window>
3. MainViewModel.cs
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;public class MainViewModel : ViewModelBase
{public RelayCommand RecoverCommand { get; private set; }public MainViewModel(){// 初始化命令,模拟 ESC 键触发RecoverCommand = new RelayCommand(SendRecoveryCommand);}private void SendRecoveryCommand(){// 发送恢复消息到 "fanxuan" 通道Messenger.Default.Send<string>("Recovery", "fanxuan");}
}
4. ButtonViewModel.cs
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using System.Windows;public class ButtonViewModel : ViewModelBase
{public ButtonViewModel(){// 注册 "fanxuan" 通道的消息Messenger.Default.Register<string>(this,"fanxuan",message =>{if (message == "Recovery"){// 在 UI 线程执行恢复逻辑Application.Current.Dispatcher.Invoke(() =>{RecoverButtonState();});}});}private void RecoverButtonState(){// 模拟恢复按钮状态MessageBox.Show("Button state recovered!");// 实际逻辑:重置 UI 或 DICOM 数据}
}
5. 主程序(App.xaml.cs)
using GalaSoft.MvvmLight.Messaging;
using System.Windows;public partial class App : Application
{protected override void OnStartup(StartupEventArgs e){base.OnStartup(e);// 初始化 ViewModelvar mainViewModel = new MainViewModel();var buttonViewModel = new ButtonViewModel();// 设置主窗口var mainWindow = new MainWindow{DataContext = mainViewModel};mainWindow.Show();}
}
6. 运行结果
  • 点击窗口中的“Recover State”按钮,触发 RecoverCommand,发送 "Recovery" 消息。
  • ButtonViewModel 捕获消息,显示提示框“Button state recovered!”。
  • 实际应用中,可在 RecoverButtonState 中实现 UI 重置或 DICOM 数据恢复逻辑。

八、在 Windows 系统中的开发注意事项

  1. Visual Studio 2017 配置

    • 确保安装 .NET Framework 4.6.1 或更高版本。
    • 使用 NuGet 包管理器安装 MvvmLightLibs(版本 5.4.1 兼容 VS2017)。
    • 若网络受限,可下载离线 NuGet 包:
      nuget install MvvmLightLibs -Version 5.4.1 -OutputDirectory .\Packages
      
  2. 调试技巧

    • 在 Visual Studio 2017 中设置断点,检查 Messenger.Default.SendRegister 的执行流程。
    • 使用 即时窗口查看 Messenger 订阅者列表(需自定义 Messenger 实现)。
    • 验证 Dispatcher.Invoke 是否正确切换到 UI 线程。
  3. 性能优化

    • 避免频繁注册/注销订阅者,建议在 ViewModel 构造时注册,析构时注销:
      public override void Cleanup()
      {Messenger.Default.Unregister(this);base.Cleanup();
      }
      
    • 使用具体 token(如 "fanxuan")减少消息广播开销。
  4. DICOM 集成

    • 在医学影像系统中,Messenger 可用于通知 UI 更新 DICOM 参数(如 FOV、TR)。
    • 示例:发送 DICOM 文件加载完成消息:
      Messenger.Default.Send<string>("DICOMLoaded", "fanxuan");
      

九、常见问题与解决方案

问题解决方案
消息未被接收确认 SendRegistertoken 和消息类型一致。
UI 更新失败使用 Application.Current.Dispatcher.Invoke 确保回调在 UI 线程执行。
NuGet 安装失败离线下载 MvvmLightLibs 包,导入项目:nuget install MvvmLightLibs
消息误触发Register 的回调中添加条件判断:if (message == "Recovery")

十、总结

Messenger.Default.SendMessenger.Default.Register 是 C# 中基于发布-订阅模式的强大消息传递机制,特别适合 Windows 平台的 WPF 开发。基于 Visual Studio 2017 环境,本文提供了完整的配置指南和代码示例,展示了 Messenger 在 UI 状态恢复(如历史对话中的 ESC 键触发)中的应用。核心特点:

  1. 松耦合:通过 token 实现定向通信。
  2. 线程安全:结合 Dispatcher 确保 UI 操作安全。
  3. 易用性:MVVM Light 提供简单 API,适合快速开发。

在 Windows 系统和 Visual Studio 2017 中,开发者可通过 NuGet 快速集成 MVVM Light,结合 WPF 的 Dispatcher 机制实现高效通信。建议在实际开发中添加消息内容验证和订阅者管理,以提高代码健壮性。


参考资料

  • MVVM Light 文档:http://www.mvvmlight.net/
  • Visual Studio 2017 文档:https://docs.microsoft.com/en-us/visualstudio/
  • C# 委托与事件:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/85267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js数据类型有哪些?它们有什么区别?

js数据类型共有8种,分别是undefined,null,boolean,number,string,Object,symbol,bigint symbol和bigint是es6中提出来的数据类型 symbol创建后独一无二不可变的数据类型,它主要是为了解决出现全局变量冲突的问题 bigint 是一种数字类型的数据,它可以表示任意精度格式的整数,…

Vite打包优化实践:从分包到性能提升

前言: ​​​​​​​ 随着前端应用功能的增加&#xff0c;项目的打包体积也会不断膨胀&#xff0c;影响加载速度和用户体验。本文介绍了几种常见的打包优化策略&#xff0c;通过Vite和相关插件&#xff0c;帮助减少项目体积、提升性能&#xff0c;优化加载速度。 rollup-plugi…

C++语法系列之模板进阶

前言 本次会介绍一下非类型模板参数、模板的特化(特例化)和模板的可变参数&#xff0c;不是最开始学的模板 一、非类型模板参数 字面意思,比如&#xff1a; template<size_t N 10> 或者 template<class T,size_t N 10>比如&#xff1a;静态栈就可以用到&#…

html5的响应式布局的方法示例详解

以下是HTML5实现响应式布局的5种核心方法及代码示例: 1. 媒体查询(核心方案) /* 默认样式(移动优先) */ .container {padding: 15px; }/* 中等屏幕(平板) */ @media (min-width: 768px) {.container {padding: 30px;max-width: 720px;} }/* 大屏幕(桌面) */ @media …

数字化转型进阶:精读41页华为数字化转型实践【附全文阅读】

该文档聚焦华为数字化转型实践&#xff0c;核心内容如下&#xff1a; 转型本质与目标&#xff1a;数字化转型是通过数字技术穿透业务&#xff0c;实现物理世界与数字世界的融合&#xff0c;目标是支撑主业成功、提升体验与效率、探索模式创新。华为以 “平台 服务” 为核心&am…

C++ - STL #什么是STL #STL的版本 #闭源开源 #STL的六大组件

文章目录 前言 一、什么是STL 二、STL的版本 1、原始版本 2、P.J.版本 3、RW版本 4、SGI版本 三、闭源、开源 四、STL的六大组件 总结 前言 路漫漫其修远兮&#xff0c;吾将上下而求索&#xff1b; 一、什么是STL STL(standard template libaray 标准模板库)&#…

智慧康养护理:科技重塑老龄化社会的健康守护体系

在我国迈入深度老龄化社会的背景下&#xff0c;智慧康养护理作为融合科技与人文的创新模式&#xff0c;正成为提升老年人生活质量、减轻家庭照护压力、促进健康老龄化的重要路径。我们将从核心概念、关键技术、实际应用与未来趋势四个维度&#xff0c;为您呈现智慧康养护理的全…

权威认证与质量保障:第三方检测在科技成果鉴定测试中的核心作用

科技成果鉴定测试是衡量科研成果技术价值与应用潜力的关键环节&#xff0c;其核心目标在于通过科学验证确保成果的可靠性、创新性和市场适配性。第三方检测机构凭借其独立性、专业性和权威性&#xff0c;成为科技成果鉴定测试的核心支撑主体。本文从测试流程、第三方检测的价值…

Linux.docker.k8s基础概念

1.Linux基本命令 cat 查看文件内容。 cd 进入目标目录。 ll 查询当前路劲下文件的详细信息。 ls 查询当前路劲下的文件。 touch 建立一个文件。 mkdir 建立一个文件夹。 rm 删除文件或者目录。 mv 移动目录和重新命名文件。 unzip 解压。 top 查看当前线程的信息。 find …

Python小白的蜕变之旅:从环境搭建到代码规范(1/10)

摘要&#xff1a;全文围绕 Python 编程展开&#xff0c;先是介绍如何搭建 Python 开发环境&#xff0c;推荐使用 Anaconda 和 VSCode&#xff0c;并详细说明了二者的安装及配置步骤&#xff0c;包括安装 Anaconda、安装 VSCode 并配置 Python 插件、选择 Anaconda 的 Python 解…

linux 1.0.7

用户和权限的含义与作用 linux中的用户和文件 用户的权限是非常重要的 而且有些程序需要使用管理员身份去执行 这些都是非常重要的 不可能让所有的人拥有所有的权限 这样的工具可以避免非法的手段来修改计算机中的数据 linux之所以安全还是权限管理做的很棒 每个登录的用户都有…

【第4章 图像与视频】4.6 结合剪辑区域来绘制图像

文章目录 前言示例 前言 本节将综合运用图像处理、离屏 canvas 以及剪辑区域等技术实现墨镜效果。 示例 主线程代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport&qu…

UV 包管理工具:替代 pip 的现代化解决方案

安装 方法一&#xff1a;使用安装脚本 # macOS 和 Linux curl -LsSf https://astral.sh/uv/install.sh | sh# Windows PowerShell powershell -c "irm https://astral.sh/uv/install.ps1 | iex" 方法二&#xff1a;使用包管理器 # macOS (Homebrew) brew install uv#…

Java注解规范与使用详解

注解中的空值限制 在Java注解中,元素值不允许使用null引用。这是注解使用中的一项重要约束规则,违反该规则将导致编译错误。需要注意的是,虽然禁止使用null值,但允许为String类型元素指定空字符串(“”),为数组类型元素指定空数组({})。 空值约束示例 以下两种注解用法…

从零开始的数据结构教程(八)位运算与状态压缩

&#x1f3a9; 标题一&#xff1a;位运算基础——魔术师的二进制手套 位运算是一种直接操作数字二进制位的运算方式&#xff0c;它高效且巧妙&#xff0c;就像魔术师戴上了二进制手套&#xff0c;能够精准地操控每一个比特。理解位运算是深入学习状态压缩和其他底层优化技巧的…

GraalVM加持下的Quarkus极速启动

1. 引言 1.1 Quarkus与云原生时代的挑战 随着云原生架构的普及,传统Java应用在部署效率、资源消耗和冷启动性能方面逐渐暴露出短板。Spring Boot等框架虽然功能强大,但在Serverless、边缘计算等场景下表现乏力。 Quarkus 是 Red Hat 推出的一个专为云原生设计的 Java/Kotl…

vue3 el-input type=“textarea“ 字体样式 及高度设置

在Vue 3中&#xff0c;如果你使用的是Element Plus库中的<el-input>组件作为文本域&#xff08;type"textarea"&#xff09;&#xff0c;你可以通过几种方式来设置字体样式和高度。 1. 直接在<el-input>组件上使用style属性 你可以直接在<el-input&…

Matlab中gcb、gcbh、gcs的区别

gcb&#xff1a;返回当前选中模块的完整路径名&#xff08;字符串&#xff09; gcbh&#xff1a;返回当前选中模块的句柄&#xff08;数值标识符&#xff09; gcs&#xff1a;返回当前打开或选中的子系统或顶层模型路径&#xff08;字符串&#xff09;

大语言模型的技术原理与应用前景:从Transformer到ChatGPT

目录 摘要 1. 引言 2. Transformer架构核心原理 2.1 自注意力机制 2.2 位置编码 2.3 前馈神经网络 3. 从GPT到ChatGPT的演进 3.1 GPT系列模型架构 3.2 训练流程优化 4. 应用场景与案例分析 4.1 代码生成 4.2 文本摘要 4.3 问答系统 5. 挑战与未来方向 5.1 当前技…

Flink Table API 编程入门实践

Flink Table API 编程入门实践 前言 Apache Flink 是目前大数据实时计算领域的明星产品&#xff0c;Flink Table API 则为开发者提供了声明式、类似 SQL 的数据处理能力&#xff0c;兼具 SQL 的易用性与编程 API 的灵活性。本文将带你快速了解 Flink Table API 的基本用法&am…