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

C#动态数据继承优化:如何避免子类重复实现Data属性?

解决方案推荐

1. 抽象基类+泛型中间类(兼顾统一访问与DRY原则)

这是最平衡的方案,既支持List<A>统一处理所有子类,又避免了每个子类重复实现Data属性的代码。

实现代码

// 基础抽象类,保留所有公共属性
public abstract class A
{
    public int Id { get; set; }
    public string Name { get; set; }
    // 定义统一访问的抽象属性
    public abstract object DataAsObject { get; set; }
}

// 泛型中间类,封装强类型Data的实现逻辑
public abstract class A<T> : A
{
    public T Data { get; set; }
    // 自动映射到基类的抽象属性,无需子类重复编写
    public override object DataAsObject
    {
        get => Data;
        set => Data = (T)value;
    }
}

// 实际子类只需指定Data类型,无冗余代码
public class B : A<DataForB> { }
public class C : A<DataForC> { }

优势

  • 完全符合DRY原则:重复逻辑只在泛型中间类A<T>中实现一次
  • 支持统一处理:List<A>可以存储所有子类实例,通过DataAsObject访问数据
  • 保留类型安全:如果知道具体子类类型,可强转为A<DataForB>直接使用强类型的Data属性

2. 基类封装反射逻辑(子类零修改)

如果不想改动现有子类结构,可以把反射逻辑封装在基类中,通过缓存优化性能,同时提供统一的访问入口。

实现代码

public class A
{
    public int Id { get; set; }
    public string Name { get; set; }
    
    // 缓存每个类型的Data属性,避免重复反射
    private static readonly Dictionary<Type, PropertyInfo> _dataPropCache = new();

    // 统一访问的动态属性
    public dynamic Data
    {
        get
        {
            var type = GetType();
            if (!_dataPropCache.TryGetValue(type, out var prop))
            {
                prop = type.GetProperty("Data") ?? throw new InvalidOperationException("子类未定义Data属性");
                _dataPropCache[type] = prop;
            }
            return prop.GetValue(this);
        }
        set
        {
            var type = GetType();
            if (!_dataPropCache.TryGetValue(type, out var prop))
            {
                prop = type.GetProperty("Data") ?? throw new InvalidOperationException("子类未定义Data属性");
                _dataPropCache[type] = prop;
            }
            prop.SetValue(this, value);
        }
    }
}

// 子类保持原有定义不变
public class B : A
{
    public DataForB Data { get; set; }
}

优势

  • 子类无需任何修改,直接复用现有代码
  • 反射逻辑仅封装一次,性能优于手动重复反射(缓存避免重复查找属性)
  • 调用简单:直接通过a.Data访问,动态类型自动适配子类的Data类型

3. 访问者模式(适合差异化Data处理场景)

如果你的核心需求是对不同类型的Data执行差异化逻辑,而非单纯的统一访问,访问者模式可以避免大量is/as类型判断,让代码更优雅。

实现代码

// 定义访问者接口,对应每种Data类型的处理方法
public interface IDataVisitor
{
    void Visit(DataForB data);
    void Visit(DataForC data);
    // 扩展其他Data类型的Visit方法
}

// 基类定义接受访问者的抽象方法
public abstract class A
{
    public int Id { get; set; }
    public string Name { get; set; }
    public abstract void Accept(IDataVisitor visitor);
}

// 子类实现Accept方法,传递自身的Data给访问者
public class B : A
{
    public DataForB Data { get; set; }
    public override void Accept(IDataVisitor visitor)
    {
        visitor.Visit(Data);
    }
}

public class C : A
{
    public DataForC Data { get; set; }
    public override void Accept(IDataVisitor visitor)
    {
        visitor.Visit(Data);
    }
}

// 具体访问者实现不同Data的处理逻辑
public class DataProcessor : IDataVisitor
{
    public void Visit(DataForB data)
    {
        // 处理DataForB的业务逻辑
    }

    public void Visit(DataForC data)
    {
        // 处理DataForC的业务逻辑
    }
}

使用方式

List<A> items = new List<A> { new B(), new C() };
var processor = new DataProcessor();
foreach (var item in items)
{
    item.Accept(processor);
}

优势

  • 避免类型判断:无需在业务逻辑中写if (item is B b) { ... }
  • 符合开闭原则:新增Data类型只需扩展访问者接口和子类,不修改现有逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:17:49