Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic 'TThis' for fluent classes

I'm constructing a fluent interface where I have a base class that contains the bulk of the fluent logic, and a derived class that add some specialized behavior. The problem I'm facing is the return type of the fluent methods in the base class when called from an instance of the derived type. After invoking a method of the base class, only methods of the base class remain available for further fluent invocations.

Changing the order in which the methods are invoked will help it to compile, but it makes it less readable which is kinda the point for fluent interfaces. Is there a way to define some sort of "This" type for the the base class so that all methods return the same type.

Example

public class Field<T>
{
    public Field<T> Name( string name )
    {
        _name = name;
        return this;
    }
}

public SpecialField<T> : Field<T>
{
    public SpecialField<T> Special(){ return this; }
}


// !!! Arrgh. Special is not a member of the Field<T> class.
var specialField = new SpecialField()
    .Name( "bing" )
    .Special();

Broken Solution

I've tried solving it by doing something like the following but it's not valid C# :( but at least expresses how I'd like to code the interface.

public class Field<T,TThis> : TThis
    where TThis : Field<T,TThis>
{
    public TThis Name( string name ){...}
}

public SpecialField<T> : Field<T,SpecialField<T>>
{
    public TThis Special(){ return this; }
}
like image 665
Paul Alexander Avatar asked Nov 05 '09 02:11

Paul Alexander


People also ask

What are fluent methods?

A fluent interface is an object-oriented API that depends largely on method chaining. The goal of a fluent interface is to reduce code complexity, make the code readable, and create a domain specific language (DSL). It is a type of method chaining in which the context is maintained using a chain.

What is fluent design pattern?

Fluent is an open-source, cross-platform design system that gives designers and developers the frameworks they need to create engaging product experiences—accessibility, internationalization, and performance included.

What is fluent DSL?

In software engineering, a fluent interface is an object-oriented API whose design relies extensively on method chaining. Its goal is to increase code legibility by creating a domain-specific language (DSL). The term was coined in 2005 by Eric Evans and Martin Fowler.

What is .NET fluent?

Fluent.Net is a C# implementation of Project Fluent, a localization framework designed to unleash the expressive power of the natural language. Project Fluent keeps simple things simple and makes complex things possible. The syntax used for describing translations is easy to read and understand.


1 Answers

After poking around some other fluent APIs I found how to do it. It's not quite as clean, but it works well. Basically you introduce an intermediary base class for each derived type that you want to use and it passes the "TThis" type to the actual implementation.

Sample

public class FieldBase<T,TThis> 
    where TThis : FieldBase<T,TThis>
{
    private string _name;
    public TThis Name( string name ) 
    {
        _name = name;
        return (TThis)this;
    }
}

public class Field<T> : FieldBase<T,Field<T>>{}

public class SpecialFieldBase<T,TThis> : FieldBase<T,TThis>
    where TThis : SpecialFieldBase<T,TThis>
{
    public TThis Special(){ return (TThis)this; }
}

public class SpecialField<T> : SpecialFieldBase<T,SpecialField<T>>{}


// Yeah it works!
var specialField = new SpecialField<string>()
    .Name( "bing" )
    .Special();
like image 135
Paul Alexander Avatar answered Sep 21 '22 20:09

Paul Alexander