C#如何实现发布订阅模式?C#事件聚合器Pub/Sub教程

来源:编程网作者:北京SEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《C#如何实现发布订阅模式?C#事件聚合器Pub/Sub教程》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#如何实现发布订阅模式?C#事件聚合器Pub/Sub教程》有用,将其分享出去将是对创作者最好的鼓励。

发布订阅模式是一种消息通信模式,发送者也就是发布者不会直接将消息发送给特定的接收者也就是订阅者,而是通过事件聚合器作为中间层进行消息转发,实现发布者和订阅者的解耦。这种模式在模块化开发、跨组件通信场景中应用非常广泛。

C#如何实现发布订阅模式?C#事件聚合器Pub/Sub教程

发布订阅模式的核心概念

发布订阅模式主要包含三个核心角色:

  • 发布者:负责产生消息,将消息发送到事件聚合器中,不需要知道有哪些订阅者会接收消息。
  • 订阅者:负责定义消息处理逻辑,向事件聚合器注册自己感兴趣的消息类型,当对应消息发布时自动触发处理逻辑。
  • 事件聚合器:作为中间枢纽,管理所有的订阅关系,接收发布者发送的消息并转发给对应的订阅者。

基础事件聚合器实现

我们可以先实现一个简单的泛型事件聚合器,支持任意类型的消息发布和订阅。核心思路是用一个字典存储消息类型和对应的处理委托列表。

using System;
using System.Collections.Generic;

// 事件聚合器接口
public interface IEventAggregator
{
    // 订阅指定类型的消息
    void Subscribe<TMessage>(Action<TMessage> handler);
    // 取消订阅指定类型的消息
    void Unsubscribe<TMessage>(Action<TMessage> handler);
    // 发布指定类型的消息
    void Publish<TMessage>(TMessage message);
}

// 基础事件聚合器实现
public class EventAggregator : IEventAggregator
{
    // 存储消息类型和对应的处理委托列表
    private readonly Dictionary<Type, List<Delegate>> _handlers = new Dictionary<Type, List<Delegate>>();

    public void Subscribe<TMessage>(Action<TMessage> handler)
    {
        var messageType = typeof(TMessage);
        // 如果不存在该消息类型的处理列表,先创建
        if (!_handlers.ContainsKey(messageType))
        {
            _handlers[messageType] = new List<Delegate>();
        }
        // 添加处理委托
        _handlers[messageType].Add(handler);
    }

    public void Unsubscribe<TMessage>(Action<TMessage> handler)
    {
        var messageType = typeof(TMessage);
        if (_handlers.ContainsKey(messageType))
        {
            _handlers[messageType].Remove(handler);
            // 如果处理列表为空,移除该消息类型的记录
            if (_handlers[messageType].Count == 0)
            {
                _handlers.Remove(messageType);
            }
        }
    }

    public void Publish<TMessage>(TMessage message)
    {
        var messageType = typeof(TMessage);
        if (_handlers.ContainsKey(messageType))
        {
            // 遍历所有处理委托并执行
            foreach (var handler in _handlers[messageType])
            {
                // 将委托转换为对应类型的Action执行
                ((Action<TMessage>)handler).Invoke(message);
            }
        }
    }
}

使用示例

我们定义两个消息类型,模拟发布者和订阅者的交互过程。

// 定义消息类型1:用户登录消息
public class UserLoginMessage
{
    public string UserName { get; set; }
    public DateTime LoginTime { get; set; }
}

// 定义消息类型2:订单创建消息
public class OrderCreatedMessage
{
    public int OrderId { get; set; }
    public decimal Amount { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        // 创建事件聚合器实例
        IEventAggregator eventAggregator = new EventAggregator();

        // 订阅者1:处理用户登录消息
        eventAggregator.Subscribe<UserLoginMessage>(msg =>
        {
            Console.WriteLine($"用户登录通知:用户{msg.UserName}于{msg.LoginTime}登录系统");
        });

        // 订阅者2:处理订单创建消息
        eventAggregator.Subscribe<OrderCreatedMessage>(msg =>
        {
            Console.WriteLine($"订单创建通知:订单{msg.OrderId}已创建,金额{msg.Amount}元");
        });

        // 发布者发布用户登录消息
        eventAggregator.Publish(new UserLoginMessage
        {
            UserName = "张三",
            LoginTime = DateTime.Now
        });

        // 发布者发布订单创建消息
        eventAggregator.Publish(new OrderCreatedMessage
        {
            OrderId = 1001,
            Amount = 299.9m
        });

        // 取消用户登录消息的订阅
        Action<UserLoginMessage> loginHandler = msg =>
        {
            Console.WriteLine($"用户登录通知:用户{msg.UserName}于{msg.LoginTime}登录系统");
        };
        eventAggregator.Unsubscribe(loginHandler);

        // 再次发布用户登录消息,此时没有订阅者会处理
        eventAggregator.Publish(new UserLoginMessage
        {
            UserName = "李四",
            LoginTime = DateTime.Now
        });
    }
}

高级优化点

上述基础实现可以满足简单场景的需求,在实际高级应用中还可以做以下优化:

  • 支持弱引用委托,避免订阅者被事件聚合器强引用导致无法被垃圾回收,解决内存泄漏问题。
  • 支持异步消息处理,允许订阅者的处理逻辑是异步方法,事件聚合器可以异步转发消息。
  • 增加消息过滤功能,订阅者可以指定过滤条件,只有满足条件的消息才会被处理。
  • 支持消息优先级,高优先级的消息可以先被处理,或者按照优先级顺序转发给订阅者。

注意事项

在使用C#实现发布订阅模式时需要注意以下几点:

  • 消息类型尽量使用不可变类型,避免消息在传递过程中被修改导致不可预期的问题。
  • 订阅者处理逻辑尽量保持轻量,不要做耗时操作,避免阻塞消息发布线程。
  • 及时取消不需要的订阅,避免无效的处理逻辑执行,也减少内存占用。
  • 事件聚合器如果是单例模式,需要注意线程安全问题,上述基础实现没有做线程安全处理,多线程场景下需要加锁或者使用线程安全的集合。
发布订阅模式的核心是解耦,不要为了使用模式而使用模式,如果组件之间本身耦合度很低,直接调用反而更清晰,不需要强行引入事件聚合器。

C#发布订阅模式事件聚合器Pub/Sub修改时间:2026-07-18 08:24:28

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。