ExcelDNA RTD对接ASP.NET SignalR后topic更新未触发注册函数问题求助
问题原因&修正方案
1. 基础代码错误
你当前的RTD类名是SignalRServer,但构造函数名写为TradesRtdServer,会直接导致编译失败,先将构造函数名修正为和类名一致。
2. ProgID不匹配且未显式声明
仅添加[ComVisible(true)]特性不足以保证RTD服务的ProgID符合预期,系统自动生成的ProgID可能和你在XlCall.RTD中传入的参数不一致,且你当前传入的Excel.AddIn.Trading.SignalRServer和实际类的命名空间DMT.Excel.AddIn+类名SignalRServer完全不符,Excel无法匹配到对应的RTD服务实例。
修正方法:给RTD类显式添加[ProgId]特性,且XlCall.RTD的第一个参数和该特性值完全一致。
3. SignalR回调参数类型不兼容
你当前在_connection.On中使用object类型接收推送数据,若推送的是自定义复杂对象,Excel无法直接识别,会忽略更新。建议显式指定为Excel支持的基础类型(如字符串、数字),复杂对象可先序列化为JSON字符串再传入UpdateValue。
修正后代码
RTD服务代码
using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR.Client; using ExcelDna.Integration; using ExcelDna.Integration.Rtd; namespace DMT.Excel.AddIn { [ComVisible(true)] // 显式指定ProgId,和XlCall.RTD的第一个参数完全匹配 [ProgId("DMT.Excel.AddIn.SignalRServer")] public class SignalRServer : ExcelRtdServer { private HubConnection _connection; private List<Topic> _topics = new List<Topic>(); // 构造函数名和类名保持一致 public SignalRServer() { _connection = new HubConnectionBuilder() .WithUrl("http://localhost:5000/api/test/hub") .WithAutomaticReconnect() .Build(); // 显式指定接收数据类型为Excel可识别的基础类型 _connection.On<string>("Test", m => { foreach (Topic topic in _topics) { topic.UpdateValue(m); } }); // 添加异常捕获避免连接失败无日志 _ = Task.Run(async () => { try { await _connection.StartAsync(); } catch (Exception ex) { DmtAddIn.Logger.Error(ex, "SignalR连接启动失败"); } }); } protected override bool ServerStart() { DmtAddIn.Logger.Information("ServerStart"); return true; } protected override void ServerTerminate() { // 退出时释放SignalR连接 _connection?.DisposeAsync(); DmtAddIn.Logger.Information("ServerTerminate"); } protected override object ConnectData(Topic topic, IList<string> topicInfo, ref bool newValues) { DmtAddIn.Logger.Information("ConnectData: {0} - {{{1}}}", topic.TopicId, string.Join(", ", topicInfo)); if(!_topics.Contains(topic)) _topics.Add(topic); return ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA); } protected override void DisconnectData(Topic topic) { _topics.Remove(topic); DmtAddIn.Logger.Information("DisconnectData: {0}", topic.TopicId); } } }
自定义函数代码
[ExcelFunction(Name = "SignalR.Test.RTD")] public static object GetSignalRMessages() { // ProgID和RTD类的[ProgId]特性值完全一致 return XlCall.RTD("DMT.Excel.AddIn.SignalRServer", null, "Test"); }
额外检查项
- 调试时在
ConnectData方法添加断点,确认单元格输入=SignalR.Test.RTD()时该方法被触发,若未触发则说明ProgID注册失败,可清理旧插件注册表后重新编译加载 - 确认SignalR推送的数据可以正常转换为你指定的接收类型,避免类型转换失败导致更新不生效
内容的提问来源于stack exchange,提问作者jo31
相关产品推荐
相关产品推荐

