C# 派生类上的派生属性/字段:';继承阶梯&x27;在容器类及其一个字段上

C# 派生类上的派生属性/字段:';继承阶梯&x27;在容器类及其一个字段上,c#,inheritance,C#,Inheritance,如果已经回答了,我想提前道歉。由于我不知道如何在标题中恰当地表达它,我可能错过了另一个类似的问题。我看到了,这是相似的,但我不认为它是完全相同的,因为它并没有像我将要描述的那样的层次结构 假设我有一个基类和基字段,以及一个作用于该字段的方法DoStuff() class MyContainer { MyField field = new MyField(); protected virtual void DoStuff() { field.foo

如果已经回答了,我想提前道歉。由于我不知道如何在标题中恰当地表达它,我可能错过了另一个类似的问题。我看到了,这是相似的,但我不认为它是完全相同的,因为它并没有像我将要描述的那样的层次结构

假设我有一个基类和基字段,以及一个作用于该字段的方法
DoStuff()

class MyContainer
{
    MyField field = new MyField();
    
    protected virtual void DoStuff()
    {
        field.foo1 = "a";
        field.foo2 = "b";
    }
}
现在,我想扩展MyContainer,并创建MyContainerExt,它还应该包含MyField(MyFieldExt)的派生版本。MyContainerExt将重写DoStuff()以在MyFieldExt上执行一些额外的操作,但我也希望完成基类中的DoStuff():本质上,我希望从基类MyContainer中执行“基类”操作和初始化,并添加额外的初始化,这些初始化可能需要在派生的MyFieldExt上添加新字段/属性

要在上面添加,假设现在我想要MyContainerExtExt,它有一个从MyFieldExt派生的字段(即MyFieldExtExt),我想在父类已经在做的事情的基础上再做一些事情

老实说,我不知道如何以一种有组织、无臭味的方式来解决这个问题。给你一个想法,这将是我想要的(如果你能用派生类型覆盖属性,我知道你不能):

这一点一开始可能没有意义,但我希望有一个层次结构,在这个结构中,每个“继承级别”上可能有多个变体:

> MyContainer
>> MyContainerExt1, MyContainerExt2...
>>> MyContainerExt1Ext1, MyContainerExt1Ext2, MyContainerExt2Ext1, MyContainerExt2Ext2...
我想考虑这些类在其中一个字段上必须做的一个共同因素:MyContainer在其MyField类型字段上需要做的大部分(如果不是全部的话)将需要由其所有的子级完成,但需要注意的是,MyContainer的子级也有MyField的派生版本。我还希望这是一个相对容易扩展的解决方案:我不希望有一个解决方案能够“管理”这一阶梯,使其最多支持3个继承级别,如示例中所示。我可能不需要更多,但我希望我正在制作的代码在将来的MyContainerExtExt…Ext或任何情况下都可以扩展

我对结构一点也不固定:它可以是基于属性的,也可以是子类必须重新实现的私有字段,等等。我只是想要一种相对干净的方法来实现初始化/处理MyField的派生版本,而无需将父对象的DoStuff()中的所有行复制到子对象的DoStuff()方法中(这会破坏继承点)

如果有人想知道,我需要它来在高度分层的WPF应用程序(ViewModel==MyContainer,Model==MyField)中构建我的模型和ViewModels,但这不应该影响我所想的问题

顺便说一句,我正在使用.NET4.5.2,所以在此之前欢迎使用任何新技巧

编辑: 我最终得到了与下面中间人的答案非常相似的东西。这是我在问之前想做的,但它似乎不合适,所以我想再次检查是否有标准/更好的方法来做这件事。我的最终结构如下:

class MyContainer
{
    protected MyField Foo {get; set; }

    public MyContainer()
    {
        Foo = new MyField();
    }
    
    protected virtual void DoStuff()
    {
        Foo.foo1 = "a";
        Foo.foo2 = "b";
    }
}


class MyContainerExt: MyContainer
{
    public MyContainerExt()
    {
        Foo = new FieldExt();  // no need to override anything for this to work
    }

    protected override void DoStuff()
    {
        base.DoStuff();  // The DoStuff() from the base class is applied
        
        MyFieldExt foo = (MyFieldExt)Foo;  // The cast always works, since Foo is initialized as FieldExt
        foo.foo3 = "c";  // Potentially, foo3 and foo4 are fields added to MyFieldExt that
        foo.foo4 = "d";  //    the base class MyField knows nothing about
    }
}


class MyContainerExtExt: MyContainerExt
{
    public MyContainerExtExt()
    {
        Foo = new FieldExtExt();  // no need to override anything for this to work
    }

    protected override void DoStuff()
    {
        base.DoStuff();  

        MyFieldExtExt foo = (MyFieldExtExt)Foo;  // The cast always works, since Foo is initialized as FieldExtExt
        Foo.foo5 = "e";  // Again, foo5 and foo6 are fields added to MyFieldExtExt that
        Foo.foo6 = "f";  //    the base class MyFieldExt knows nothing about
    }
}

您可以执行以下操作。考虑到你的基本类型

class MyContainer
{
    abstract MyField Foo {get; set; }

    protected virtual void DoStuff()
    {
        Foo.foo1 = "a";
        Foo.foo2 = "b";
    }
}
无需在派生类型中重新声明
MyField
,只需将其强制转换为更具体的类型:

class MyContainerExt: MyContainer
{

    protected override void DoStuff()
    {
        base.DoStuff();
        var specificFoo = Foo as MyFieldExt; //this cast will always succeed
        specificFoo.foo3 = "c";  
        specificFoo.foo4 = "d";
    }
}

从公共抽象类MyContainer开始,其中T:MyField{public abstract T Foo{get;set;}这可能有帮助,也可能没有帮助..我认为继承在这里不合适。嘿,Sweeper,你如何使用组合巧妙地解决这个问题?我认为继承听起来像是最有组织的方法,考虑到我在看一个类的树结构,“级别”中的每个类都必须实现以前级别的所有内容ls和扩展它…mjwills,事实上我对泛型不太熟悉…我看到了类似的东西,但感觉它不能轻易扩展到“继承阶梯”下…是吗?@Arce11我的建议有帮助吗?@mjwills,正如我说的,我对泛型不太熟悉。现在我接近完成我的结构代码(不是玩具示例)尝试和使用casting,因为这或多或少已经是我想要的方式。如果失败了,我会研究在我的基类上使用泛型。但是,如果你能提供一个例子,这肯定会有帮助。我想我每次都需要在MyFieldExt特定的字段上使用casting,对吗?这不会是be这是一个问题,因为在我的例子中,我不经常处理这些字段。但是,DoStuff()方法结束后,MyFieldExt特定字段是否保存在Foo属性(MyField类型)上?@Arce11:是的,它们将保留在内存中。
class MyContainerExt: MyContainer
{

    protected override void DoStuff()
    {
        base.DoStuff();
        var specificFoo = Foo as MyFieldExt; //this cast will always succeed
        specificFoo.foo3 = "c";  
        specificFoo.foo4 = "d";
    }
}