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

如何在C#中不使用接口模拟实现多重继承?

在.NET Framework中实现多功能包复用的几种方案

1. 扩展方法 + 接口(无状态/轻量逻辑首选)

针对XML版本兼容读写这类无状态或仅依赖接口约定的逻辑,扩展方法是最直接的复用方式。先定义标记接口,再通过扩展方法为接口添加默认实现,类只需实现接口就能复用这些逻辑,无需重复编写版本切换等通用代码。

示例:XML版本化读写

先定义核心接口,预留子类需实现的版本专属逻辑:

public interface IXmlSavable
{
    int CurrentVersion { get; }
    void ReadVersion1(XElement element);
    void ReadVersion2(XElement element);
    XElement WriteVersion1();
    XElement WriteVersion2();
}

编写扩展方法封装通用的版本切换逻辑:

public static class XmlSavableExtensions
{
    public static void Read(this IXmlSavable savable, XElement root)
    {
        int version = int.TryParse(root.Attribute("Version")?.Value, out var v) ? v : 1;

        switch (version)
        {
            case 1: savable.ReadVersion1(root); break;
            case 2: savable.ReadVersion2(root); break;
            default: throw new NotSupportedException($"不支持的XML版本:{version}");
        }
    }

    public static XElement Write(this IXmlSavable savable)
    {
        XElement root = savable.CurrentVersion switch
        {
            1 => savable.WriteVersion1(),
            2 => savable.WriteVersion2(),
            _ => throw new InvalidOperationException($"无效的当前版本:{savable.CurrentVersion}")
        };
        root.SetAttributeValue("Version", savable.CurrentVersion);
        return root;
    }
}

使用时,类只需实现版本专属方法,直接调用扩展方法即可:

public class UserData : IXmlSavable
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Email { get; set; } // V2新增属性

    public int CurrentVersion => 2;

    public void ReadVersion1(XElement root)
    {
        Name = root.Element("Name").Value;
        Age = int.Parse(root.Element("Age").Value);
    }

    public void ReadVersion2(XElement root)
    {
        ReadVersion1(root); // 复用V1逻辑
        Email = root.Element("Email").Value;
    }

    public XElement WriteVersion1()
    {
        return new XElement("UserData",
            new XElement("Name", Name),
            new XElement("Age", Age));
    }

    public XElement WriteVersion2()
    {
        var root = WriteVersion1();
        root.Add(new XElement("Email", Email));
        return root;
    }
}

// 调用示例
var user = new UserData();
user.Read(XElement.Load("user.xml"));
user.Write().Save("user.xml");

2. 组合模式(有状态逻辑首选)

对于“暂停事件触发锁”这类需要维护内部状态(如暂停计数)的逻辑,组合模式比继承更灵活。将每个功能封装为独立的处理类,在目标类中通过成员变量引入这些处理类,实现对应的接口并委托调用处理类的方法。

示例:事件暂停锁

先封装事件暂停逻辑为独立类:

public class EventPauseManager
{
    private int _pauseCount;

    public bool IsPaused => _pauseCount > 0;

    public void Pause()
    {
        Interlocked.Increment(ref _pauseCount);
    }

    public void Resume()
    {
        Interlocked.Decrement(ref _pauseCount);
    }

    // 辅助方法:判断是否允许触发事件
    public bool CanTrigger() => _pauseCount == 0;
}

定义对应的接口:

public interface IEventPausable
{
    void PauseEvents();
    void ResumeEvents();
}

在目标类中组合并实现接口:

public class OrderService : IEventPausable, IXmlSavable
{
    private readonly EventPauseManager _pauseManager = new EventPauseManager();
    private readonly XmlSavableHandler _xmlHandler;

    public event EventHandler<OrderEventArgs> OrderCreated;

    public OrderService()
    {
        _xmlHandler = new XmlSavableHandler(this);
    }

    // 实现IEventPausable接口
    public void PauseEvents() => _pauseManager.Pause();
    public void ResumeEvents() => _pauseManager.Resume();

    public void CreateOrder(Order order)
    {
        // 业务逻辑...
        // 触发事件前判断是否暂停
        if (_pauseManager.CanTrigger())
        {
            OrderCreated?.Invoke(this, new OrderEventArgs(order));
        }
    }

    // 委托XML处理逻辑给组合类
    public int CurrentVersion => 1;
    public void ReadVersion1(XElement element) => _xmlHandler.ReadVersion1(element);
    public void ReadVersion2(XElement element) => throw new NotImplementedException();
    public XElement WriteVersion1() => _xmlHandler.WriteVersion1();
    public XElement WriteVersion2() => throw new NotImplementedException();
}

// XML处理组合类示例
public class XmlSavableHandler
{
    private readonly OrderService _target;

    public XmlSavableHandler(OrderService target)
    {
        _target = target;
    }

    public void ReadVersion1(XElement root)
    {
        // 读取XML数据到_target的属性
    }

    public XElement WriteVersion1()
    {
        // 生成_target对应的XML元素
        return new XElement("OrderService");
    }
}

3. 抽象类 + 接口组合(单一主逻辑继承,其他功能组合)

如果某个功能是类的核心逻辑,可以用抽象类封装,其他非核心功能用组合模式引入。比如业务类核心是XML可保存,就继承XmlSavableBase抽象类,同时组合EventPauseManager实现事件暂停功能。

public abstract class XmlSavableBase : IXmlSavable
{
    public abstract int CurrentVersion { get; }
    public abstract void ReadVersion1(XElement element);
    public abstract void ReadVersion2(XElement element);
    public abstract XElement WriteVersion1();
    public abstract XElement WriteVersion2();

    // 封装版本切换逻辑(抽象类可直接实现接口方法)
    public void Read(XElement root)
    {
        int version = int.TryParse(root.Attribute("Version")?.Value, out var v) ? v : 1;
        switch (version)
        {
            case 1: ReadVersion1(root); break;
            case 2: ReadVersion2(root); break;
            default: throw new NotSupportedException($"不支持的XML版本:{version}");
        }
    }

    public XElement Write()
    {
        XElement root = CurrentVersion switch
        {
            1 => WriteVersion1(),
            2 => WriteVersion2(),
            _ => throw new InvalidOperationException($"无效的当前版本:{CurrentVersion}")
        };
        root.SetAttributeValue("Version", CurrentVersion);
        return root;
    }
}

// 业务类继承抽象类,同时组合其他功能
public class Product : XmlSavableBase, IEventPausable
{
    private readonly EventPauseManager _pauseManager = new EventPauseManager();

    public event EventHandler ProductUpdated;

    public override int CurrentVersion => 2;

    // 实现抽象类的版本读写方法...

    // 实现IEventPausable接口
    public void PauseEvents() => _pauseManager.Pause();
    public void ResumeEvents() => _pauseManager.Resume();

    public void UpdateProduct()
    {
        // 业务逻辑...
        if (_pauseManager.CanTrigger())
        {
            ProductUpdated?.Invoke(this, EventArgs.Empty);
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:50:55