Another C# trick: Fluents, Inheritance and Extension Methods

Here’s a scenario which Damien and I encountered recently.

We needed a way of specifying Facets for properties on Entities, i.e. things like Nullable, MaxLength, Precision etc.

And we needed a class hierarchy because different types of properties have different sets of available facets.

The base class of the hierarchy is called PropertyConfiguration which defines a series of Fluent methods that are shared by all sub types:

public abstract class PropertyConfiguration
{
private bool _nullable;
public virtual PropertyConfiguration Nullable()
{
_nullable = true;
return this;
}
public virtual PropertyConfiguration NonNullable()
{
_nullable = false;
return this;
}
}

An example of a sub-type is StringPropertyConfiguration, which in addition to allowing you to specify Nullability() also allows you to set the MaxLength(..) of the string.

public class StringPropertyConfiguration: PropertyConfiguration
{
private int? _maxLength;
public StringPropertyConfiguration MaxLength(int maxLength)
{
_maxLength = maxLength;
return this;
}
}

Each of these fluent methods return this, so you can chain calls together like this:

var nameConfiguration = new StringPropertyConfiguration()
.MaxLength(100)
.Nullable();

This *looks* promising.

But there is a nasty limitation in this design.

If I change my code to this:

var nameConfiguration = new StringPropertyConfiguration()
     .Nullable()
.MaxLength(100);

It doesn’t compile.

If you look at the signature for PropertyConfiguration.Nullable() you can see it returns PropertyConfiguration (not StringPropertyConfiguration) so MaxLength(…) isn’t available.

Ouch.

Now we don’t want to subject our customers to these sort of arbitrary ordering restrictions.

So what do you do?

Well you could just do something like this:

public new StringPropertyConfiguration Nullable()
{
return base.Nullable() as StringPropertyConfiguration;
}

This works but is really annoying if you have a lot of effected methods, or a deep / wide inheritance hierarchy.

Thankfully Damien had a much better idea…

First replace the public fluent methods on PropertyConfiguration, with a good old fashioned property like this:

public abstract class PropertyConfiguration
{
private bool _nullable;
public bool Nullable {
get { return _nullable; }
set { _nullable = value; }
}
}

Then write an extension method that looks like this:

public static T Nullable<T>(this T propertyConfiguration)
where T: PropertyConfiguration
{
propertyConfiguration.Nullable = true;
return propertyConfiguration;
}

Now you can call Nullable() on any class that derives from PropertyConfiguration, and get by that class back rather than the base PropertyConfiguration class.

So with this in place you can write this:

var nameConfiguration = new StringPropertyConfiguration()
     .Nullable()
.MaxLength(100);

And all we did is write one property, and one generic extension method.

Nifty!

There is a meta-lesson buried in all this.

If you want to put Fluents on classes with an inheritance hierarchy, the easiest way is probably to write your classes the old fashion way (with non-fluent properties and methods) and when you’ve done that add a series of generically constrained extensions methods to add the required fluents.

Happy coding.