C# - 多态性问题

sam*_*tin 1 c# polymorphism fluent chaining

我有一些类,我喜欢链式方法,以提供流畅的配置风格.

例如

public class BaseFoo
{
    private bool _myProp = false;
    public [[[BaseFoo?]]] SetMyProperty()
    {
        this._myProp = true;
        return this;
    }
}

public class DerivedFoo : BaseFoo
{
    public bool _derivedProp = false;
    public DerivedFoo SetDerivedPropery()
    {
        this._derivedProp = true;
        return this;
    }
}
Run Code Online (Sandbox Code Playgroud)

当我使用base方法返回BaseFoo类型时,问题显然是在尝试将它们链接在一起时.显然我可以将它转换回DerivedFoo,但是有一种简单的方法可以返回派生类类型的对象.

我能想到的唯一方法就是将构造函数链接在一起并将父类型传递给初始构造函数,但需要使用语法.

另一种方法是为每个子类提供类似的代理方法,但返回派生类型.

 DerivedFoo foo = new DerivedFoo();
        foo.SetMyProperty().SetDerivedPropery(); // wont work because the SetMyProperty returns type of BaseFoo
        foo.SetDerivedPropery().SetMyProperty(); // works because I know i'm calling the method of the derived class first
        (foo.SetMyProperty() as DerivedFoo).SetDerivedPropery(); // works as i'm casting result of base method to derived type
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

提前致谢,

山姆

Dan*_*rth 8

仿制药怎么样?

public class BaseFoo<TDerived> where TDerived : BaseFoo<TDerived>
{
    private bool _myProp = false;
    public TDerived SetMyProperty()
    {
        this._myProp = true;
        return (TDerived)this;
    }
}

public class DerivedFoo : BaseFoo<DerivedFoo>
{
    public bool _derivedProp = false;
    public DerivedFoo SetDerivedPropery()
    {
        this._derivedProp = true;
        return this;
    }
}
Run Code Online (Sandbox Code Playgroud)

但我真的认为继承层次结构的不同层次之间的耦合是一个很大的设计问题.
我建议你看看其他流畅的界面,比如Fluent NHibernate,Rhino Mocks等,看看"大"的人怎么做;-)

你也可以使用像这样的扩展方法,一种流畅的升级.这对我来说似乎更清洁.

public static class FooFluentExtensions
{
    public static T SetMyProperty<T>(this T foo) where T : BaseFoo
    {
        foo.MyProp = true;
        return foo;
    }

    public static T SetDerivedPropery<T>(this T foo) where T : DerivedFoo
    {
        foo.DerivedProp = true;
        return foo;
    }
}

static void Main()
{
    DerivedFoo foo = new DerivedFoo();
    // works, because SetMyProperty returns DerivedFoo
    foo.SetMyProperty().SetDerivedPropery();

    BaseFoo baseFoo = new BaseFoo();
    baseFoo.SetMyProperty();

    // doesn't work (and that's correct), because SetMyProperty returns BaseFoo
    // baseFoo.SetMyProperty().SetDerivedPropery();
}
Run Code Online (Sandbox Code Playgroud)

您可以封装您希望流畅的每个方法.