views:

194

answers:

2

I've been working away (http://tinyurl.com/m4hzjb) on this Fluent API for instantiating ASP.NET controls and feel I now have something that appears to work well. I'm looking for some feedback and opinions... good, bad or indifferent. Would you find this useful? Any technical issues you foresee? Room for improvement?

Here's a very basic usage sample for creating a standard TextBox control. Only two properties/methods are implemented, but API could easily be expanded to support full property feature set of control(s).

USAGE

Factory.TextBox()
        .ID("TextBox1")
        .Text("testing")
        .RenderTo(this.form1);

// The above TextBox Builder is functionally same as:

TextBox textbox = new TextBox();
textbox.ID = "TextBox1";
textbox.Text = "testing";

this.form1.Controls.Add(textbox);

// Or: 

this.form1.Controls.Add(new TextBox {
    ID = "TextBox1",
    Text = "testing"
});

Here's the full ControlBuilder class.

BUILDER

public partial class Factory
{
    public static TextBoxBuilder TextBox()
    {
        return new TextBoxBuilder(new TextBox());
    }
}

public abstract class ControlBuilder<TControl, TBuilder> 
    where TControl : Control
    where TBuilder : ControlBuilder<TControl, TBuilder>
{
    public ControlBuilder(TControl control)
    {
        this.control = control;
    }

    private TControl control;

    public virtual TControl Control
    {
        get
        {
            return this.control;
        }
    }

    public virtual void RenderTo(Control control)
    {
        control.Controls.Add(this.Control);
    }

    public TBuilder ID(string id)
    {
        this.Control.ID = id;
        return this as TBuilder;
    }
}

public abstract class TextBoxBuilder<TTextBox, TBuilder> : ControlBuilder<TTextBox, TBuilder>
    where TTextBox : TextBox
    where TBuilder : TextBoxBuilder<TTextBox, TBuilder>
{
    public TextBoxBuilder(TTextBox control) : base(control) { }

    public TBuilder Text(string text)
    {
        this.Control.Text = text;
        return this as TBuilder;
    }
}

public class TextBoxBuilder : TextBoxBuilder<TextBox, TextBoxBuilder>
{
    public TextBoxBuilder(TextBox control) : base (control) { }
}
+2  A: 

I question the need here. To me, this:

Factory.TextBox()
    .ID("TextBox1")
    .Text("testing")
    .RenderTo(this.form1);

Is far less clear than:

this.form1.Controls.Add(new TextBox {
        ID = "TextBox1",
        Text = "testing"
    });

What is Factory? What happens if we forget the "RenderTo" line?

The first is not nearly as obvious to me, and going to be less maintainable, since it would be very difficult to extend this for custom controls (where you don't know the properties in advance), etc.

Reed Copsey
I agree. I question the need as well. The project started as just trying to figure out if this style of syntactic sugar was possible for control building. But, I do question the need and whether it just confuses things further.
jlang
Arguing which is clearer is just expressing a preference. Fluent is like a coding style, but I can't say weather it's more readable
Oplopanax
@Oplopanax: I agree, and that's why I explicitly prefixed my statement with "To me". However, this isn't providing new functionality, but rather a different programming abstraction. Any abstraction should only be written and preferred if it provides certain clear advantages, either in readability, maintainability, performance, etc. In this case, I don't see how this improves the current accepted practice.
Reed Copsey
A: 

I love how Fluent APIs work, and this might be a nice way to configure dynamic controls.

I have the following points:

  • the Fluent API style is just that, a style. It accomplishes the same thing as the traditional functional programming style, with a different esthetic.
  • Many users just use the Forms designer to design controls, and this is enough. Unless you're creating controls at runtime, it won't be used very much.
  • Further to the above, most of the runtime controls I've created tend to have some if-then-else logic. The Fluent style lends itself to simple configurations, but tends to become unwieldy when there's lots of logic in the building process.
  • I'd be hard pressed to convince myself or other architects on the team that this had any advantages other than readability or stylistic over the traditional approach.
  • Finally, my production code would have to depend on another library, and there's always the remote chance that you may have introduced a bug.

Ultimately, I have to say good for you to take this on. It's a great exercise, and someone may use it. Make it open source, and in a few years it might become standard.

Oplopanax