Control Builders & ASP.NET Generic Control Classes

Since the release of .NET 2.0 and ASP.NET 2.0 I was very disappointed that new language power of C# 2.0 is not available for ASP.NET developers.  It was stressed at the time of release by multiple people (see here, here and here).  While generic classes are not supported in ASP.NET markup in general, it seemed to me that it is still possible to benefit from generic in ASP.NET in many cases.

ASP.NET supports "control builders" abstraction controlling different aspects of code generation.  The most important is that control builders define the actual type of page field for the control and actual class of the control to be instantiated. 

Moreover, if control builder returns generic type, ASP.NET generates code which successfully instantiate it and page field is also correct. 

As a small sample I created a generic enumeration drop-down list control.  This control has a TypedValue property returning the currently selected enumeration member.  Type of this property is controlled from the EnumType attribute in the ASPX markup.  The following markup

  <t:EnumDropDown runat="server" EnumType="MyEnum" ID="TheDropDown" />

 

allows to use TheDropDown in code behind in a statically typed manner:

   MyEnum? atr = TheDropDown.TypedValue;

If you find the temporary C# file for the web page, you can see that TheDropDown field is declared as:

   protected global::CouldBeDone.GenericControls.EnumDropDown<MyEnum>
                                                              TheDropDown;


The trick in getting this behavior is in custom control builder class which tells ASP.NET to use generic version of the class instead of non-generic.  So, at first I created a non-generic version of EnumDropDown and decorated it with ControlBuilder attribute.

    [ControlBuilder(typeof(EnumDropDownControlBuilder))]
    public class EnumDropDown : DropDownList {
        private string m_EnumType;
        public string EnumType {
            get {
                return m_EnumType;
            }
            set { m_EnumType = value; }
        }
    }

The generic version of EnumDropDown which is used in web pages provides all useful features (like type Value property).

    public class EnumDropDown<T> : EnumDropDown
        where T : struct {

        public T? TypedValue {
          //// implementation removed
        }
    }

The EnumDropDownControlBuilder does only one thing.  It replaces the type of control to be instantiated.

    public override void Init(TemplateParser parser, ControlBuilder
              
parentBuilder, Type type,

               
string tagName, string id, IDictionary attribs) {
        string enumTypeName = (string)attribs["EnumType"];
 
       Type enumType = Type.GetType(enumTypeName);
        Type dropDownType =
               typeof(EnumDropDown<>).MakeGenericType(enumType);

        base.Init(parser, parentBuilder, dropDownType,
                  tagName, id, attribs);

    }

This was a very simple case.   The most important place where I like to see static typing in ASP.NET is data binding. 
I tried to apply this technique to get typed Repeater and new ListView controls and stop using Eval and type casting in data binding expressions.  I managed to get a result, but unfortunately it requires wrapping templates into special placeholder controls.  I will probably make one more post about generic classes in ASP.NET, if I can get typed data binding more simple.

If you like to see live EnumDropDown, here is the sample Visual Studio project:

GenericEnumDropDown.zip

The web site was create in beta 2 of Visual Studio 2008, but as it targets .net 2.0, I hope it should run fine in VS 2005 as well.

12 Comments

Comments have been disabled for this content.