1

I have some classes that i'd like chain methods of to provide a fluent style of config.

e.g.

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;
    }
}

The problem is clearly when trying to chain these together, as soon as I use the base method the returned type of BaseFoo. Obviously I could cast this back to DerivedFoo, but is there a simply way of returning an object of the derived class type.

The only way I can think of doing it is chaining constructors together and passing in the parent type to the initial constructor but usure of syntax.

Another way would be to have like proxy methods for each of the subclass', but returning the derived type.

 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

any ideas?

Thanks in advance,

Sam

sambomartin
  • 6,663
  • 7
  • 40
  • 64
  • I think the problem is that the base class shouldn't rely too much on the derived classes. – Cheng Chen May 06 '11 at 08:39
  • Btw, `return this;` in an instance method of a class brings me very bad feelings... I don't know why, something is wrong. – Cheng Chen May 06 '11 at 08:42
  • why would you not just do foo.SetDerivedProperty and foo.SetMyProperty – Sisyphus May 06 '11 at 08:50
  • @Danny Chen , I agree it feels wrong. When I see a method returning it's own type, I think it implies that the class is immutable and that you need to assign it again. `myDerivedFoo = myDerivedFoo.SetDerivedPropery();` similar to `myString = myString.Trim();` – Buh Buh May 06 '11 at 09:17
  • It has been discussed before: http://stackoverflow.com/questions/2278781/fluent-interfaces-and-inheritance-in-c – Anders Fjeldstad May 06 '11 at 11:48

3 Answers3

8

What about generics?

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;
    }
}

But I really think that the coupling between the different levels of the inheritance hierarchy is a big design problem.
I suggest you have a look at other fluent interfaces like Fluent NHibernate, Rhino Mocks etc, to see how the "big" guys do it ;-)

You could also use extension methods like this, sort of an fluent upgrade. This seems cleaner to me.

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();
}

You could encapsulate every method that you want to be fluent.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • hi, yeah did try that. cannot cast this (BaseFoo) to TDerived though – sambomartin May 06 '11 at 08:37
  • Sure you can. I just tested it. Maybe you forgot the `where` part? – Daniel Hilgarth May 06 '11 at 08:38
  • beg your pardon, missing explicit class on return. thanks, I'll see how it works out. Was about to ditch the fluent interface and go with properties. – sambomartin May 06 '11 at 08:43
  • Quick on the draw! :) - added my solution anyway since it is ever-so-slightly different. But I'll up-vote anyway. – Eben Roux May 06 '11 at 08:44
  • In this example you wouldn't be able to instantiate the BaseFoo on it's own? that right? – sambomartin May 06 '11 at 08:48
  • 1
    thanks all, think I'll stick to properties for this implementation, it's not worth all the extra aggravation for what is just as easily achieved using props like Flynn suggested. a fluent interface would have been nice but not practical for inheritance hierarchy i need and the fact i need to instantiate base objects too. – sambomartin May 06 '11 at 08:55
  • @sambomartin: For educational reasons, I updated my answer anyhow, to show you a way that seems a bit cleaner. – Daniel Hilgarth May 06 '11 at 09:02
  • +1. We do this a lot. But it's almost always used for creating fluent apis in test code. (The readablility of some of the tests really benefit from a fluent style.) When refactoring test code, we sometimes end up with base classes for the fluent apis - precisely what this question (and answer) is all about. – Christoffer Lette May 06 '11 at 09:08
  • @daniel: yeah, that does look cleaner. good for future reference. thanks – sambomartin May 06 '11 at 09:42
3

Personally, I loathe this style of coding.

Can't you make them properties? Then you can do

DerivedFoo foo = new DerivedFoo
{
  MyProperty = true,
  DerivedProperty = true
};

It's much cleaner and more readable.

Flynn1179
  • 11,925
  • 6
  • 38
  • 74
1

One option is to do something like this:

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

    public class DerivedFoo : BaseFoo<DerivedFoo> { ... }

But it depends on your scenario.

Eben Roux
  • 12,983
  • 2
  • 27
  • 48