Fluent Silverlight – Fluent API and inheritance

Please view the table of content of this series for reference.

Introduction

In my last post I showed how we  can implement a fluent API to help us construct instances of specific classes. When using a fluent API the code is in general much more readable. In this post I want to go one step further and show how we can implement a hierarchical fluent API.

Defining a base expression

Our objects that we use in our applications are often inherited from some base class as in the following simple example.

image

Here we have an abstract Person base class from which the Employee class inherits. We might have another class e.g. Customer that also inherits from Person. If we now want to implement a fluent API for the construction of Employee- and/or Customer objects then it makes sense that our fluent API is also hierarchically organized. We might want to build a parallel hierarchy of PersonExpression, EmployeeExpression and CustomerExpression where the latter two inherit from the first expression.

But now we have a problem. From my previous article we know that each method in a fluent API has to return the expression itself. But if we now implement say the LastName() method in the PersonExpression like this

public abstract class PersonExpression
{
    private string lastName;
    ...
 
    public PersonExpression LastName(string value)
    {
        lastName = value;
        return thisInstance();
    }
 
    ...
}

then when used in the context of an EmployeeExpression (where EmployeeExpression inherits from PersonExpression)

Employee john = new EmployeeExpression()
    .FirstName("John")
    .LastName("Doe")
    ...

we will not be able to get to any of the members defined in the EmployeeExpression any more since our continuation is of type PersonExpression and NOT of type EmployeeExpression. With other words: whenever we use a method of the base expression in our fluent expression then we loose the context!

Thus we have to find another solution. The solution is to introduce a generic parameter which will be used as the type of the return value of the methods of our expression classes. Consequently we will write

public abstract class PersonExpression<THIS>
    where THIS : PersonExpression<THIS>
{
    private string lastName;
    ...
 
    public THIS LastName(string value)
    {
        lastName = value;
        return thisInstance();
    }
 
    ...
}

If we use the generic parameter THIS instead of a concrete (base) expression, then we will never loose the context. Please note also that the LastName method does not return ‘this’ any more but rather the return value of the function thisInstance which is defined as follows

protected THIS thisInstance()
{
    return (THIS)this;
}

So we never should return directly this any more in our expression hierarchy but rather thisInstance().

But wait, we have still one more problem: since we want to define the implicit type conversion in the base class we also have to introduce the target type as a generic parameter such as that we can then write

public static implicit operator TARGET(PersonExpression<THIS, TARGET> expression)
{
    var target = new TARGET();
    expression.BuildUp(target);
    return target;
}

where the BuildUp function is defined as follows

protected virtual void BuildUp(TARGET target)
{
    ...
}

this method will be overriden by the child expressions to build-up the target object.

The full code for the PersonExpression will now look like this

public abstract class PersonExpression<THIS, TARGET>
    where THIS : PersonExpression<THIS, TARGET>
    where TARGET : Person, new()
{
    private string lastName;
    private string firstName;
    private DateTime dateOfBirth;
    private Gender gender;
 
    public THIS LastName(string value)
    {
        lastName = value;
        return thisInstance();
    }
 
    public THIS FirstName(string value)
    {
        firstName = value;
        return thisInstance();
    }
 
    public THIS DateOfBirth(DateTime value)
    {
        dateOfBirth = value;
        return thisInstance();
    }
 
    public GenderExpression<PersonExpression<THIS, TARGET>> Gender
    {
        get{ return new GenderExpression<PersonExpression<THIS, TARGET>>(this, x => gender = x);}
    }
 
    protected THIS thisInstance()
    {
        return (THIS)this;
    }
 
    protected virtual void BuildUp(TARGET target)
    {
        target.LastName = lastName;
        target.FirstName = firstName;
        target.DateOfBirth = dateOfBirth;
        target.Gender = gender;
    }
 
    public static implicit operator TARGET(PersonExpression<THIS, TARGET> expression)
    {
        var target = new TARGET();
        expression.BuildUp(target);
        return target;
    }
}

Note how the two generic parameters are restricted by their respective where filters. This restriction is very important to make the whole concept work.

The full code for the EmployeeExpression is given below

public class EmployeeExpression : PersonExpression<EmployeeExpression, Employee>
{
    private DateTime hireDate;
    private decimal yearlySalary;
 
    public EmployeeExpression HireDate(DateTime value)
    {
        hireDate = value;
        return thisInstance();
    }
 
    public EmployeeExpression YearlySalary(decimal value)
    {
        yearlySalary = value;
        return thisInstance();
    }
 
    protected override void BuildUp(Employee target)
    {
        base.BuildUp(target);
        target.HireDate = hireDate;
        target.YearlySalary = yearlySalary;
    }
}

and the expression can now be used in the following way

Employee john = new EmployeeExpression()
    .FirstName("John")
    .LastName("Doe")
    .DateOfBirth(new DateTime(1964, 4, 14))
    .HireDate(new DateTime(2007, 3, 1))
    .YearlySalary(90000);

With the aid of some “generics magic” we are now able to implement a hierarchically structured fluent API for our objects we want to construct. This is a very important pattern we used when implementing Fluent Silverlight.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Gabriel Schenker

Gabriel N. Schenker started his career as a physicist. Following his passion and interest in stars and the universe he chose to write his Ph.D. thesis in astrophysics. Soon after this he dedicated all his time to his second passion, writing and architecting software. Gabriel has since been working for over 12 years as an independent consultant, trainer, and mentor mainly on the .NET platform. He is currently working as chief software architect in a mid-size US company based in Austin TX providing software and services to the pharmaceutical industry as well as to many well-known hospitals and universities throughout the US and in many other countries around the world. Gabriel is passionate about software development and tries to make the life of developers easier by providing guidelines and frameworks to reduce friction in the software development process. Gabriel is married and father of four children and during his spare time likes hiking in the mountains, cooking and reading.
This entry was posted in fluent Silverlight, How To, introduction, Silverlight. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.bjro.de Bjoern Rochel

    Thanks for posting this. I stumbled onto the “this problem” when using inheritance with fluent apis several times in the past, but never found a solution I was 100% satisfied with. What I a difference a little method can make (We were missing the trick with the generic THIS ;-().