Generic Expression Builder

July 25th, 2009

I blogged about fluent interfaces and expression builders a couple of times before. For this post, I want to share a base class that I’ve been using for taking away some of the burden when creating expression builders for domain classes.

Here’s the expression I’m after:

var document = DocumentBuilder.BuildDocument()
    .AuthoredBy("Stephen Hawking")
    .Titled("The Universe in a Nutshell")
    .TaggedWith(tag => tag.Named("Physics"))
    .Build();

This creates an instance of a domain class named Document with the name of the author, its title and with an associated tag. Let me first show the code of the expression builders that make this happen.

public interface IDocumentAuthorBuilder
{
    IDocumentTitleBuilder AuthoredBy(String author);
}

public interface IDocumentTitleBuilder
{
    IDocumentTagBuilder Titled(String title);
}

public interface IDocumentTagBuilder : IBuilder<Document>
{
    IDocumentTagBuilder TaggedWith(Action<ITagBuilder>
                                                buildUsing);
}

public class DocumentBuilder : Builder<Document>,
                               IDocumentAuthorBuilder,
                               IDocumentTitleBuilder,
                               IDocumentTagBuilder
{
    private DocumentBuilder()
    {}

    public static IDocumentAuthorBuilder BuildDocument()
    {
        return new DocumentBuilder();
    }

    IDocumentTitleBuilder AuthoredBy(String author)
    {
        ProvideValueFor(document => document.Author, author);
        return this;
    }

    IDocumentTagBuilder Titled(String title)
    {
        ProvideValueFor(document => document.Title, title);
        return this;
    }

    public IDocumentTagBuilder TaggedWith(Action<ITagBuilder>
                                                    buildUsing)
    {
        var tagBuilder = new TagBuilder(tag =>
            ProvideValueFor(document => document.Tags, tag));

        buildUsing(tagBuilder);
        return this;
    }
}

public interface ITagBuilder
{
    void Named(String name);
}

public class TagBuilder : ITagBuilder
{
    private readonly Action<Tag> _afterBuildAction;

    public TagBuilder(Action<Tag> afterBuildAction)
    {
        _afterBuildAction = afterBuildAction;
    }

    public void Named(String name)
    {
        var tag = new Tag(name);
        _afterBuildAction(tag);
    }
}

The expression builders all provide progressive interfaces. Also notice that the DocumentBuilder derives from a base class named Builder. This class provides a method ProvideValueFor that is used to feed the base class with the name of a property and a corresponding value. Collections are also supported. Here’s the code for the Builder class.

public interface IBuilder<T>
{
    T Build();
}

public abstract class Builder<T> : IBuilder<T>
{
    private Dictionary<PropertyInfo, Object> PropertiesAndValues
    { get; set; }

    protected Builder()
    {
        PropertiesAndValues =
            new Dictionary<PropertyInfo, Object>();
    }

    public static implicit operator T(Builder<T> builder)
    {
        return builder.Build();
    }

    protected void ProvideValueFor(Expression<Func<T, Object>> expression,
                                   Object value)
    {
        var property = ReflectionHelper.GetProperty(expression);

        if(false == PropertiesAndValues.ContainsKey(property))
            RegisterPropertyAndValue(property, value);
        else
            SetPropertyAndValue(property, value);
    }

    private void SetPropertyAndValue(PropertyInfo property,
                                     Object value)
    {
        if(IsCollection(property))
        {
            var values = (List<Object>) PropertiesAndValues[property];
            values.Add(value);
        }
        else
        {
            PropertiesAndValues[property] = value;
        }
    }

    private void RegisterPropertyAndValue(PropertyInfo property,
                                          Object value)
    {
        if(IsCollection(property))
            PropertiesAndValues.Add(property,
                                    new List<Object>() { value });
        else
            PropertiesAndValues.Add(property, value);
    }

    private static Boolean IsCollection(PropertyInfo property)
    {
        if(property.PropertyType == typeof(String))
            return false;

        var collectionType = typeof(IEnumerable<>);
        return IsCollectionOfType(collectionType,
                                  property.PropertyType);
    }

    private static Boolean IsCollection(FieldInfo field)
    {
        var collectionType = typeof(ICollection<>);
        return IsCollectionOfType(collectionType, field.FieldType);
    }

    private static Boolean IsCollectionOfType(Type collectionType,
                                              Type type)
    {
        if(collectionType.Name == type.Name)
            return true;

        var interfaces = type.GetInterfaces();
        return interfaces.Has(@interface =>
            @interface.Name == collectionType.Name);
    }

    public T Build()
    {
        var typeToBuild = typeof(T);
        if(false == HasParameterlessConstructor(typeToBuild))
            throw new InvalidOperationException(
                "No parameterless constructor.");

        var instance = (T)Activator.CreateInstance(typeToBuild, true);
        foreach(var entry in PropertiesAndValues)
        {
            var property = entry.Key;
            if(IsCollection(property))
                SetCollectionValuesFor(property, instance,
                                       (List<Object>) entry.Value);
            else
                SetValueFor(property, instance, entry.Value);
        }

        return instance;
    }

    private static Boolean HasParameterlessConstructor(Type type)
    {
        const BindingFlags bindingFlags =
            BindingFlags.Public |
            BindingFlags.NonPublic |
            BindingFlags.Instance;

        var defaultConstructor =
            type.GetConstructor(bindingFlags, null,
                                new Type[0], null);
        return null != defaultConstructor;
    }

    private static void SetValueFor(PropertyInfo property, T instance,
                                    Object value)
    {
        property.SetValue(instance, value, null);
    }

    private static void SetCollectionValuesFor(PropertyInfo property,
                                               T instance,
                                               List<Object> values)
    {
        var backingField = BackingFieldResolver.GetBackingField(property);
        if(false == IsCollection(backingField))
        {
            var message = String.Format(
                ResourceLoader<Builder<T>>
                    .GetString("InvalidCollectionType"), property.Name);

            throw new InvalidOperationException(message);
        }

        var collection = property.GetValue(instance, null);
        foreach(var value in values)
        {
            const BindingFlags bindingFlags =
                BindingFlags.Public |
                BindingFlags.Instance |
                BindingFlags.InvokeMethod;

            backingField.FieldType
                .InvokeMember("Add", bindingFlags, null,
                              collection, new[] { value });
        }
    }
}

Using this approach, its no longer necessary to make any compromise of exposing property setters or a dedicated constructor just for serving the expression builders. The Builder class uses refection to set the value of a property or to fill a collection. The BackingFieldResolver is a class I picked up from this post. Very cool stuff!

I have only used this approach in a couple of side projects, but let me know you think.

Till next time.

Jan Van Ryswyck

  • Chris Martin

    While it may be a fun exercise in learning language features. I’ve come to absolutely loath most of these “fluent” thingamajiggers.

    All that work to accomplish what exactly?

    This?:

    var doc = new Document();
    doc.Author = “Stephen Hawking”;
    doc.Title = “The Universe in a Nutshell”;
    doc.AddTag(new Tag{Name = “Physics”});

  • http://elegantcode.com Jan Van Ryswyck
  • http://www.kygeek.com/daily-links/daily-links-for-sunday-july-26th-2009 Daily Links for Sunday, July 26th, 2009

    [...] Generic Expression Builder | Elegant Code [...]

  • http://huseyint.com/ Huseyin Tufekcilerli

    Do you consider C# 4.0′s optional parameters as a solution for this situation:

    /* ctor */
    public Document(
    string author = “”,
    string title = “”,
    IList tags = null)
    {
    /* … */
    }

    /* usage */
    var documnet = new Document(
    author: “Stephen Hawking”,
    title: “John Doe”,
    tags: new[] { “Physics” });

  • http://www.alvinashcraft.com/2009/07/26/dew-drop-weekend-edition-july-25-26-2009/ Dew Drop – Weekend Edition – July 25-26, 2009 | Alvin Ashcraft’s Morning Dew

    [...] Generic Expression Builder (Jan Van Ryswyck) [...]

  • http://elegantcode.com/ Jan Van Ryswyck

    @Huseyin: I’m not a big fan of optional parameters. Using the Builder class doesn’t require a dedicated constructor nor property setters. OO at its best.

  • Steve Py

    Fluent has it’s places but it’s a heavyweight. I’d argue that Setters don’t break encapsulation; They *can* break it if you just wrap your private field with a getter & setter it’s no different than just having a public field. However, setters can define the rules around if/how private data can be modified. IMO that preserves encapsulation. Fluent constructs have their flaws and abuses as well. (I’m currently in the process of testing some of their bending/breaking points)

    Personally, I currently lean towards setters, especially now that they “fixed” them:
    public string myProperty
    {
    get {}
    internal set {}
    }

  • http://elegantcode.com Jan Van Ryswyck

    @Steve Changing state of an object should be done through behavior. I don’t consider a property setter to be the right place for this kind of behavior (although technically yes it compiles down to a method). With setters, we get objects that temporarily become invalid while changing the different setters. With behavior we specify a method that performs our state changes in a single atomic operation.

  • http://blog.cwa.me.uk/2009/07/27/the-morning-brew-398/ Reflective Perspective – Chris Alcock » The Morning Brew #398

    [...] Generic Expression Builder – Jan Van Ryswyck shares some generic code which helps in the construction of Fluent Interfaces for expression builders for domain classes, using reflection to set properties. [...]

  • Valeriu Caraulean

    @Jan Van Ryswyck
    But even fluent interfaces are not the way to add behavior to your objects. Under the covers, fluent interface will do mostly to same actions as properties – setting values on object, and will do it without any context.

    If you want to add behavior it would sit in object itself or in specialized classes, like factories:
    document.UpdateDetails(author, title, [] tags);

  • http://smellegantcode.wordpress.com Daniel Earwicker

    I’d like to second Chris Martin’s comment, but go further:

    var doc = new Document
    {
    Author = “Stephen Hawking”,
    Title = “The Universe in a Nutshell”,
    Tags = new[]
    {
    new Tag { Name = “Physics” }
    }
    };

    Where ‘Tags’ is an IEnumerable property.

    Or, even better (if these things are required for the constructed object to make sense):

    var doc = new Document(“Stephen Hawking”,
    “The Universe in a Nutshell”,
    new Tag { Name = “Physics” });

    Where the third parameter is ‘params Tag[] tags’ to allow multiple tags.

    Fluent methods are a syntax hack used in less expressive languages (Java, C ) and have no real place in C# 3.0 anymore.

  • http://www.johnnyhall.co.uk Johnny Hall

    Hi. Great stuff, I’ve got builders liberally sprinkled around my domain and I think they are invaluable.

    Any chance you could bundle the code up into a zip? It has a couple of dependencies (ReflectionHelper, BackingFieldResolver (which itself seems to depend on Mono)) and I think you have an extension method or two in there(Has and Name on Type).

    Setters are the work of the devil. There’s a view that Getters aren’t too clever either but that’s a whole nother can o worms.

  • Valeriu Caraulean

    @Johnny Hall
    Can you give few examples how you’re using it in your domain?

    Because i’m strugling to see any usefulness of fluent interfaces outside of places where a kind of configuration API is required. Here, done right, the fluency works very well because of it’s discoverable nature.

    But to use it as a replacement for property setters – in my opinion this sounds wrong…

  • http://www.johnnyhall.co.uk Johnny Hall

    I have a (configurable, multi-tenant) navigation system, where I have to set up pages with a bunch of properties and relationships. Without the builder, I have either created (the initial configuration) pages directly from the constructor, or from a factory. Both ways, the code very quickly ends up looking a mess.

    Now I have something like this:

    var security = NavigationBuilder
    .ForApplication(Application.Security)
    .ForTenant(Root.Tenant)
    .AddPages(
    PageBuilder.Named(“main”),
    PageBuilder.Named(“home”).AsController(),
    PageBuilder.Named(“dashboard”),
    PageBuilder.Named(“administration”).ForParent(“main”).AsController()
    )
    .Build();

    The indentation inside AddPages is simply there to make it a bit more readable.

  • http://www.johnnyhall.co.uk Johnny Hall

    Ah, ok, the indentation has disappeared. But it’s there in spirit.

  • http://www.johnnyhall.co.uk Johnny Hall

    @Valeriu Caraulean
    And I guess that code is a configuration API.

  • mh

    Is there a reflectionhelper class that goes with this?

  • http://elegantcode.com Jan Van Ryswyck

    @Valeriu: Expression builders are especially useful to create and set up an entire aggregate root with all its entities and value objects. No place for behavior. I was just making a point against setters on domain objects.

    @Johnny: Agreed on getters. Very hard to do and I’ve learned to live with them. Using static analysis for preventing procedural abuse. The code is part of a small sample app I’ve been working on. Maybe at a given point I’ll put it out there somewhere.

    This is the code for the ReflectionHelper class.
    http://snipplr.com/view/17521/reflectionhelper/

  • http://evain.net/blog Jb Evain

    That’s indeed a cool usage of the backing field resolver. Glad that it is useful to you!

  • http://elegantcode.com/2009/08/01/fluent-domain-methods/ Fluent Domain Methods | Elegant Code

    [...] my last post, I talked about a Generic Expression Builder class for easily creating domain entities through expression builders. This generic base class [...]

blog comments powered by Disqus