怪奇物语

怪奇物语

首页 新随笔 联系 管理

C# 消息分发器模式,开闭原则,类型注解,反射注册,解耦,通信管理

基于消息分发器模式反射注册,这种设计适合需要灵活扩展消息类型的场景(如通信协议、命令处理系统)。

1. 类关系图(核心设计)

使用类图展示各组件的继承、依赖和关联关系:

classDiagram direction LR class MessageTypeAttribute { + int Type + MessageTypeAttribute(int type) } class MessageHandlerBase { + abstract Task HandleAsync(string message) } class HelloMessageHandler { + override Task HandleAsync(string message) } class ByeMessageHandler { + override Task HandleAsync(string message) } class MessageDispatcher { - Dictionary<int, MessageHandlerBase> _handlers + MessageDispatcher() + async Task DispatchAsync(int type, string message) } class Program { + static async Task Main() } HelloMessageHandler --|> MessageHandlerBase ByeMessageHandler --|> MessageHandlerBase MessageTypeAttribute "1" <|-- "1" HelloMessageHandler : 标记 MessageTypeAttribute "1" <|-- "1" ByeMessageHandler : 标记 MessageDispatcher "1" *-- "*" MessageHandlerBase : 管理 MessageDispatcher "1" --> "1" MessageTypeAttribute : 读取 Program "1" --> "1" MessageDispatcher : 使用

2. 消息处理流程图(补充流程)

用流程图展示消息从分发到处理的完整流程:

flowchart TD A[Program 调用 DispatchAsync] --> B[MessageDispatcher 检查_handlers字典] B -->|存在对应type的Handler| C[调用Handler.HandleAsync] B -->|不存在| D[输出No handler for message type X] C --> E[HelloMessageHandler/ByeMessageHandler 处理消息] E --> F[完成处理] D --> F

设计思路说明

  1. 核心组件职责

    • MessageTypeAttribute:特性类,用于标记处理器对应的消息类型(如[MessageType(1)]绑定到HelloMessageHandler)。
    • MessageHandlerBase:抽象基类,定义消息处理的统一接口HandleAsync
    • HelloMessageHandler/ByeMessageHandler:具体处理器,继承基类并实现特定类型的消息处理逻辑,重写基类中的方法。
    • MessageDispatcher:分发器核心,通过反射自动注册所有带MessageTypeAttribute的处理器,根据消息类型分发到对应处理器。
    • Program:入口类,创建分发器并发起消息分发。
  2. 关键设计亮点

    • 反射注册MessageDispatcher在构造函数中通过反射扫描程序集,自动发现并注册所有消息处理器,无需手动添加。
    • 开闭原则:新增消息类型时,只需创建新的XXXMessageHandler并标记MessageTypeAttribute,无需修改分发器代码。
    • 类型绑定:通过int类型的消息标识绑定处理器,实现“类型→处理器”的映射。

源代码

DispatchDemo\ByeMessageHandler.cs


[MessageType(2)]
public class ByeMessageHandler : MessageHandlerBase
{
    public override Task HandleAsync(string message)
    {
        Console.WriteLine($"Bye handler received: {message}");
        return Task.CompletedTask;
    }
}


DispatchDemo\DispatchDemo.csproj


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

DispatchDemo\HelloMessageHandler.cs


[MessageType(1)]
public class HelloMessageHandler : MessageHandlerBase
{
    public override Task HandleAsync(string message)
    {
        Console.WriteLine($"Hello handler received: {message}");
        return Task.CompletedTask;
    }
}

DispatchDemo\MessageDispatcher.cs


using System.Reflection;

public class MessageDispatcher
{
    private readonly Dictionary<int, MessageHandlerBase> _handlers = new();

    public MessageDispatcher()
    {
        // 反射注册所有带 MessageTypeAttribute 的处理器
        var handlerTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.GetCustomAttribute<MessageTypeAttribute>() != null);

        foreach (var type in handlerTypes)
        {
            var attr = type.GetCustomAttribute<MessageTypeAttribute>();
            var handler = (MessageHandlerBase)Activator.CreateInstance(type);
            _handlers[attr.Type] = handler;
        }
    }

    public async Task DispatchAsync(int type, string message)
    {
        if (_handlers.TryGetValue(type, out var handler))
        {
            await handler.HandleAsync(message);
        }
        else
        {
            Console.WriteLine("No handler for message type " + type);
        }
    }
}

DispatchDemo\MessageHandlerBase.cs


public abstract class MessageHandlerBase
{
    public abstract Task HandleAsync(string message);
}

DispatchDemo\MessageTypeAttribute.cs


[AttributeUsage(AttributeTargets.Class)]
public class MessageTypeAttribute : Attribute
{
    public int Type { get; }

    public MessageTypeAttribute(int type) => Type = type;
}

DispatchDemo\Program.cs


using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var dispatcher = new MessageDispatcher();
        await dispatcher.DispatchAsync(1, "Hello, world!");
        await dispatcher.DispatchAsync(2, "Goodbye, world!");
        await dispatcher.DispatchAsync(3, "Unknown message");
    }
}



posted on 2025-07-03 08:00  超级无敌美少男战士  阅读(34)  评论(0)    收藏  举报