如何在C#中创建类似HubConnection.On<T1>的On<T>事件
实现类似SignalR HubConnection.On的泛型消息注册机制
核心实现思路
通过泛型方法结合类型字典存储委托,实现无需硬编码消息类型的消息处理注册与触发逻辑。
ProxyClient类完整实现
public class ProxyClient { // 按消息类型存储对应的处理委托列表 private readonly Dictionary<Type, List<Action<object>>> _messageHandlers = new(); // 泛型注册方法:绑定T类型消息的处理逻辑 public void On<T>(Action<T> handler) { var messageType = typeof(T); if (!_messageHandlers.ContainsKey(messageType)) { _messageHandlers[messageType] = new List<Action<object>>(); } // 创建包装委托,自动将object转换为T类型后调用原handler Action<object> wrappedHandler = message => handler((T)message); _messageHandlers[messageType].Add(wrappedHandler); } // 模拟消息接收与处理触发(实际场景中可替换为网络消息回调等) public void DispatchMessage(object message) { var messageType = message.GetType(); if (_messageHandlers.TryGetValue(messageType, out var handlers)) { foreach (var handler in handlers) { handler(message); } } } }
配套测试类示例
消息定义
public class MessageClass1 { public string Content { get; set; } } public class MessageClass2 { public int Id { get; set; } }
处理类定义
public class MyClass1 { public void ProcessMessage(MessageClass1 message) { Console.WriteLine($"处理MessageClass1内容:{message.Content}"); } } public class MyClass2 { public void ProcessMessage(MessageClass2 message) { Console.WriteLine($"处理MessageClass2ID:{message.Id}"); } }
调用示例
// 初始化客户端与处理实例 var client = new ProxyClient(); var class1 = new MyClass1(); var class2 = new MyClass2(); // 注册不同类型消息的处理逻辑 client.On<MessageClass1>(class1.ProcessMessage); client.On<MessageClass2>(class2.ProcessMessage); // 模拟发送消息 client.DispatchMessage(new MessageClass1 { Content = "这是第一条测试消息" }); client.DispatchMessage(new MessageClass2 { Id = 999 });
关键说明
- 无硬编码限制:通过泛型参数
T自动识别消息类型,不需要提前定义所有可能的消息类 - 多处理支持:同一消息类型可以注册多个处理方法,消息到来时所有绑定的方法都会被触发
- 类型安全:包装委托确保消息类型转换的安全性,只有匹配类型的消息才会触发对应处理逻辑
- 性能优化:提前创建强类型包装委托,避免
DynamicInvoke带来的性能开销
内容的提问来源于stack exchange,提问作者Mihaly Sogorka
相关产品推荐
相关产品推荐

