Search code examples
c#inheritancefluent

How can I make order irrelevant when calling fluent methods of inherited objects?


When extending a class with a fluent method, the order you call the fluent methods matters, due to inheritance and the type of the returned object. A fluent method from the base will return an object of the base type, which won't have any fluent methods from the inherited type. But reverse the method calls and you're fine.

For example:

public class Thing
{
  public Thing DoThing()
  {
    return this;
  }
}

public class ExtendedThing : Thing
{
  public ExtendedThing DoExtendedThing()
  {
    return this;
  }
}

// This works.
// DoExtendedThing returns an ExtendedThing object,
// which gets DoThing from Thing via inheritance
var extendedThing1 = new ExtendedThing().DoExtendedThing().DoThing();

// This doesn't work.
// DoThing returns a Thing object, which doesn't have
// DoExtendedThing on it
var extendedThing2 = new ExtendedThing().DoThing().DoExtendedThing()

How could I possibly get DoThing to not return a Thing, but instead return on object of whatever type the calling object has been extended into, even though it would have no idea what that type was at compile time.

Or do I just have to know to call the fluent methods in the "correct" order?


Solution

  • I believe this can be solved with the following pattern:

    class Base<T> where T : Base<T>
    {
        public T Thing()
        {
            return (T)this;
        }
    }
    
    class Derived : Base<Derived>
    {
        public void AnotherThing()
        {
            Console.WriteLine("Hello!");
        }
    }
    

    For the line var extended = new Derived().Thing();, extended has the ability to call AnotherThing().

    Is it what you're looking for?

    Update: as it turns out, if was already answered here