The Almighty All!

I'm developing some Builder, using "Builder" pattern.
Base class has a method "SomeMethod", returning itself, than can be used in a chain of calls during building process, like this: MyBuilderClassObject.SomeMethod().OtherMethod()...

SomeMethod is virtual and can be overwritten in descendant classes, but can be not.
So it has to return "this" as an instance of Base class.
The problem is that "OtherMethod" exists only in one of descendants, but result of SomeMethod() is Base, and it has not "OtherMethod"

public abstract class Base
{
    public virtual Base SomeMethod()
    {
        return this;
    }
}

public class Derived1 : Base
{
    public void OtherMethod()
    {
        ;
    }
}

public class Derived2 : Base
{
    public void AnotherOneMethod()
    {
        ;
    }
}

And I want to use it like this:

var d1 = new Derived1();
d1.SomeMethod().OtherMethod(); // CS1061 'Base' does not contain a definition for 'OtherMethod'

var d2 = new Derived2();
d2.SomeMethod().AnotherMethod(); // CS1061 'Base' does not contain a definition for 'AnotherMethod'
  • I know I can cast:
    ((Derived1)d1.SomeMethod()).OtherMethod() but it's too boring and ugly when the chain is long

  • I know I can use generic for SomeMethod and call it:
    d1.SomeMethod<Deriver1>().OtherMethod()
    but it's also stupid, as concret type of SomeMethod, called on Derived1 instance is obvious

  • I know I cat break up chain:
    d1 = new Derived1(); d1.SomeMethod(); d1.OtherMethod(); but this violates the idea on Builder pattern

  • I tried to dig towards covariant and contravariant interfaces, but did not succeed.

UPD:
This looks like solution for me (may be not the most beautiful, but working):

public abstract class Base<T> where T : Base<T>
{
    public virtual T SomeMethod()
    {
        return this as T;
    }
}

public class Derived : Base<Derived>
{
    public void OtherMethod()
    {
        ;
    }
}

// using:
var d1 = new Derived1();
d1.SomeMethod().OtherMethod();

UPD2: No, UPD doesn't work, when inheritance chain is longer then 1 (for class Derived2: Derived1) :(

0

There are 0 best solutions below