添加附加属性而不必覆盖基本属性

本文关键字:属性 覆盖 不必 添加 | 更新日期: 2023-09-27 18:26:00

我有许多从抽象基类派生的类。具体类通过引用基类存储在容器中。具体类具有许多属性,这些属性用于绑定到FixedDocument中的页面。

我想在运行时将传统属性添加到具体类中,这些类也将绑定到FixedDocument页面。我研究了decorator模式,但似乎我必须覆盖decorator类中的所有具体类属性,使它们可见。有没有一种方法可以添加一个从继承基本属性值的具体类派生的包装器,如下所示:

    class BaseClass
    {
        public string Name { get; set; }
    }
    class ConcreteClass : BaseClass
    {
        public int MyProperty { get; set; }
    }
    class ConcreteClassWrapper : ConcreteClass
    {
        public int AdditionalProperty { get; set; }
        public ConcreteClassWrapper(ConcreteClass cc) 
        {
            base = cc;
        }
    }
    private static void RunTime()
    {
        List<BaseClass> list = new List<BaseClass>();
        ConcreteClass cc = new ConcreteClass()
        {
            Name = "Original",
            MyProperty = 5
        };
        list.Add(cc);
        cc = new ConcreteClassWrapper(cc)
        {
            AdditionalProperty = 10
        };
    }

显然,我不能只设置"base=cc"。有没有办法做到这一点?

添加附加属性而不必覆盖基本属性

你能修改ConcreteClass使它有一个额外的构造函数吗:

class ConcreteClass : BaseClass
{
    public int MyProperty { get; set; }
    public ConcreteClass(ConcreteClass copy)
    {
        this.MyProperty = copy.MyProperty;
    }
}
class ConcreteClassWrapper : ConcreteClass
{
    public int AdditionalProperty { get; set; }
    public ConcreteClassWrapper(ConcreteClass cc)
        base(cc)
    {
    }
}

您可以想象包装器类的定义如下

class ConcreteClassWrapper : ConcreteClass
{
    public string Name { get; set; } // Inherited from BaseClass
    public int MyProperty { get; set; } // Inherited from ConcreteClass
    public int AdditionalProperty { get; set; } 
}

它包含在所有基类中声明的所有成员,因为它继承了它们。

你可以创建一个像这样的新实例(假设你有一个默认的构造函数)

var wrapper = new ConcreteClassWrapper { 
    Name = "xy", 
    MyProperty = 5, 
    AdditionalProperty = 7
};

但是,如果您希望包装器是真正的包装器,请不要从基类继承

class ConcreteClassWrapper
{
    private ConcreteClass _cc;
    public ConcreteClassWrapper(ConcreteClass cc)
    {
        _cc = cc;
    }
    public string Name { get { return _cc.Name; } set { _cc.Name = value; } }
    public string MyProperty{ get { return _cc.MyProperty; } set { _cc.MyProperty = value; } }
    public int AdditionalProperty { get; set; } 
}