You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中基于网络协议帧实例化子类的OOP优化方案咨询

优化方案:基于开闭原则重构对象实例化逻辑

1. 先明确基础结构

确保基类包含消息类型标识,所有子类继承基类:

public enum MessageType
{
    TypeA,
    TypeB,
    TypeC
}

public abstract class ClassBase
{
    public MessageType MsgType { get; set; }
    // 协议公共字段
    public int CommonId { get; set; }
    public string CommonContent { get; set; }
}

public class ClassA : ClassBase { /* 类型A特有字段 */ }
public class ClassB : ClassBase { /* 类型B特有字段 */ }
public class ClassC : ClassBase { /* 类型C特有字段 */ }

2. 用可扩展工厂替代Switch

创建一个消息工厂,通过字典注册类型与实例化逻辑,新增子类时仅需注册,无需修改工厂核心代码:

public static class MessageFactory
{
    private static readonly Dictionary<MessageType, Func<ClassBase, ClassBase>> _typeBuilders = new();

    // 初始化已有类型的构建逻辑
    static MessageFactory()
    {
        RegisterBuilder(MessageType.TypeA, baseObj => new ClassA
        {
            MsgType = baseObj.MsgType,
            CommonId = baseObj.CommonId,
            CommonContent = baseObj.CommonContent
            // 这里可以补充类型A特有字段的解析/赋值逻辑
        });

        RegisterBuilder(MessageType.TypeB, baseObj => new ClassB
        {
            MsgType = baseObj.MsgType,
            CommonId = baseObj.CommonId,
            CommonContent = baseObj.CommonContent
        });

        RegisterBuilder(MessageType.TypeC, baseObj => new ClassC
        {
            MsgType = baseObj.MsgType,
            CommonId = baseObj.CommonId,
            CommonContent = baseObj.CommonContent
        });
    }

    // 对外提供注册入口,新增子类时调用即可
    public static void RegisterBuilder(MessageType msgType, Func<ClassBase, ClassBase> builder)
    {
        if (_typeBuilders.ContainsKey(msgType))
            throw new InvalidOperationException($"类型{msgType}的构建逻辑已存在");
        _typeBuilders[msgType] = builder;
    }

    // 核心实例化方法
    public static ClassBase BuildConcreteMessage(ClassBase baseMsg)
    {
        if (_typeBuilders.TryGetValue(baseMsg.MsgType, out var builder))
            return builder(baseMsg);
        
        throw new NotSupportedException($"不支持的消息类型:{baseMsg.MsgType}");
    }
}

3. 简化事件处理器逻辑

原来的Switch逻辑直接替换为工厂调用,新增ClassD时仅需三步:

  • 给MessageType加TypeD枚举值
  • 创建ClassD继承ClassBase
  • 调用MessageFactory.RegisterBuilder注册构建逻辑
public void ProtocolRxEventHandler(byte[] frameData)
{
    // 先解析得到仅含公共信息的基类对象
    ClassBase baseMsg = ParseFrameToBase(frameData);
    
    // 工厂自动生成对应子类实例并复制公共字段
    ClassBase concreteMsg = MessageFactory.BuildConcreteMessage(baseMsg);
    
    // 通知对应模块(这里如果用多态处理,扩展成本更低)
    DispatchToModule(concreteMsg);
}

// 多态分发,新增子类时仅需加一个case
private void DispatchToModule(ClassBase msg)
{
    switch (msg)
    {
        case ClassA a: ModuleA.Handle(a); break;
        case ClassB b: ModuleB.Handle(b); break;
        case ClassC c: ModuleC.Handle(c); break;
        // 新增ClassD时加这一行:case ClassD d: ModuleD.Handle(d); break;
        default: throw new NotSupportedException();
    }
}

4. 进阶:自动反射注册(可选)

如果不想手动写注册逻辑,可以给子类加特性,通过反射自动扫描注册:

[AttributeUsage(AttributeTargets.Class)]
public class BindMessageTypeAttribute : Attribute
{
    public MessageType TargetType { get; }
    public BindMessageTypeAttribute(MessageType targetType) => TargetType = targetType;
}

// 给子类绑定类型
[BindMessageType(MessageType.TypeA)]
public class ClassA : ClassBase { }

// 修改工厂静态构造函数
static MessageFactory()
{
    // 扫描当前程序集中所有ClassBase子类
    var types = AppDomain.CurrentDomain.GetAssemblies()
        .SelectMany(a => a.GetTypes())
        .Where(t => t.IsSubclassOf(typeof(ClassBase)) && !t.IsAbstract);

    foreach (var type in types)
    {
        var attr = type.GetCustomAttribute<BindMessageTypeAttribute>();
        if (attr == null) continue;

        _typeBuilders[attr.TargetType] = baseObj => 
        {
            // 反射实例化子类
            var instance = (ClassBase)Activator.CreateInstance(type);
            // 复制公共字段(也可以用AutoMapper简化批量复制)
            instance.MsgType = baseObj.MsgType;
            instance.CommonId = baseObj.CommonId;
            instance.CommonContent = baseObj.CommonContent;
            return instance;
        };
    }
}

这种方案下,新增子类只需要定义类+加特性,完全不需要修改原有代码,彻底实现开闭原则。

核心优势

  • 新增子类时无需修改原有逻辑,仅需新增代码,符合开闭原则
  • 对象创建逻辑集中管理,符合单一职责
  • 后续维护、扩展成本极低

内容的提问来源于stack exchange,提问作者siii fsxa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 13:55:16