In the previous post, we saw a real life requirement (a custom view engine) and the intended API that the developers would use.

Let’s begin with some of the basic constructs used:

public interface IComponent
{
     //Code omitted
}

public interface IComponentContainer : IComponent
{
     List<IComponent> ChildComponents {get; set;}
     //Code omitted
}

/// Root component of our view
public class View : IComponentContainer
{
    //Code omitted
}

The View class is the root component that contains all of our other components. As you can see it is an IComponentContainer. In the code displayed in the previous post, you may remember a Panel component that contained some other components. A Panel is also an IComponentContainer.

Bear with me, there is a reason I am explaining all of this.

Lets see the TextBox component:

public class TextBox: ICustomCssEnabledComponent, 
                      IEventEnabledComponent
{
    public string Name {get; set;}
    //Code omitted
}

//Not all components will expose access to custom css 
public interface ICustomCssEnabledComponent : IComponent
{
    List<string> CssClasses {get; set;}
}

//A component that supports events will implement this interface
public interface IEventEnabledComponent : IComponent
{
    List<ComponentEvent> Events {get; set;}
}

public class ComponentEvent
{
    public string EventName {get; set;}
    public string JsHandler {get; set;}
}

Now, let’s get into the component builders that provide the fluent API we saw in the previous post.

//Provides the API for the TextBox component
public class TextBoxBuilder
{
    private TextBox _textBox;

    public TextBoxBuilder(TextBox textBox)
    {
        _textBox = textBox;
    }
    
    //Textbox specific option
    public TextBoxBuilder Name(string name)
    {
        _textBox.Name = name;
        return this;
    }
    //code omitted
}

//This is the builder that all component containers' builders inherit. 
//It provides the base entry point for adding components
public class ContainerBuilder<TModel>
{
    protected IComponentContainer _container;

    public TextBoxBuilder AddTextBoxFor<TProperty>
                    (Expression<Func<TModel,TProperty>> propertyExpression)
    {
        var textBox = new TextBox();
        //code omitted: Extracting info from the property expression like: 
        //              property name , caption (MVC style, reading attributes) etc
        return new TextBoxBuilder(textBox);
    }
     //code omitted
}

Ok, so the TextBoxBuilder is where the textbox specific options will be and each call to an option will return the builder instance so that the chain can keep going.

But what about all those properties that are inherited from the common interfaces, like ICustomCssEnabledComponent and IEventEnabledComponent. We do not want to duplicate the code for handling these properties in every builder, right?

If we try to solve the problem using inheritance, like having TextBoxBuilder inherit from a base ComponentBuilder class that contains those common options, we run into a flexibility problem.

What happens if an other component builder doesn’t need all of those methods? We would expose methods that are not appropriate is some cases and this is bad.

In the next post we will see how we are going to solve this problem, using C#’s extension methods.