如何在两个VSTO Outlook插件项目间实现事件触发与订阅
跨VSTO Outlook插件的事件触发与订阅实现
由于两个VSTO Outlook插件运行在同一个Outlook进程空间内,可以通过共享静态事件类实现跨插件的事件传递,以下是具体实现步骤和代码:
1. 定义共享事件契约
创建一个独立的类库项目(如SharedEventLibrary),用于定义事件和参数,确保两个插件都能引用该类库:
using System; namespace SharedEventLibrary { // 事件中心类,提供跨插件的事件触发与订阅入口 public static class PluginEventHub { // 定义带自定义参数的事件 public static event EventHandler<PluginDataEventArgs> DataReceived; // 触发事件的公共方法 public static void RaiseDataReceived(string data) { DataReceived?.Invoke(null, new PluginDataEventArgs(data)); } } // 自定义事件参数,用于传递数据 public class PluginDataEventArgs : EventArgs { public string Data { get; } public PluginDataEventArgs(string data) { Data = data; } } }
2. 事件触发方插件实现
在第一个插件(Sender)的功能区按钮点击事件中,调用事件中心的方法触发事件:
using SharedEventLibrary; using Microsoft.Office.Tools.Ribbon; using System; namespace OutlookPluginSender { public partial class SenderRibbon { private void SenderRibbon_Load(object sender, RibbonUIEventArgs e) { } // 功能区按钮点击:触发跨插件事件 private void btnTriggerEvent_Click(object sender, RibbonControlEventArgs e) { string payload = $"Sender插件触发事件:{DateTime.Now:yyyy-MM-dd HH:mm:ss}"; PluginEventHub.RaiseDataReceived(payload); } } }
3. 事件订阅方插件实现
在第二个插件(Receiver)中,通过功能区按钮订阅事件,并实现事件处理逻辑:
using SharedEventLibrary; using Microsoft.Office.Tools.Ribbon; using System.Windows.Forms; namespace OutlookPluginReceiver { public partial class ReceiverRibbon { private void ReceiverRibbon_Load(object sender, RibbonUIEventArgs e) { } // 功能区按钮点击:订阅跨插件事件 private void btnSubscribeEvent_Click(object sender, RibbonControlEventArgs e) { // 先取消原有订阅(避免重复订阅导致多次触发) PluginEventHub.DataReceived -= OnDataReceived; // 订阅事件 PluginEventHub.DataReceived += OnDataReceived; MessageBox.Show("已成功订阅跨插件事件"); } // 事件处理方法:接收并处理传递的数据 private void OnDataReceived(object sender, PluginDataEventArgs e) { // 切换到Outlook UI线程操作(避免跨线程访问COM对象异常) Globals.ThisAddIn.Invoke(new Action(() => { MessageBox.Show($"收到数据:\n{e.Data}", "Receiver插件通知"); })); } // 插件卸载时取消订阅,避免内存泄漏 private void ThisAddIn_Shutdown(object sender, System.EventArgs e) { PluginEventHub.DataReceived -= OnDataReceived; } } }
关键注意事项
- 程序集引用:两个插件必须引用同一个版本的
SharedEventLibrary,建议对类库进行强签名,避免类型加载冲突。 - UI线程安全:Outlook的COM对象只能在UI线程访问,事件处理逻辑需通过
Globals.ThisAddIn.Invoke切换到UI线程。 - 内存泄漏预防:在插件的
Shutdown事件中取消事件订阅,避免静态事件持有插件实例导致无法回收。
内容的提问来源于stack exchange,提问作者Ashwani Tandon
相关产品推荐
相关产品推荐

