Monday, March 21, 2011

Proof of concept for expression tree

I'm trying to get the name of strong-typed member:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

using Extensions;
using Et;

namespace Et
{
    class Program
    {
        static void Main(string[] args)
        {
            var p = new Person();

            Console.WriteLine("Extension method:");
            ((HtmlHelper<Person>)null).TextBoxFor(x => x.Lastname);
            ((HtmlHelper<Person>)null).TextBoxFor(x => x.Age);

            Console.WriteLine("\nNon-extension method:");
            InputFor<Person, string>(x => x.Lastname);
            InputFor<Person, int>(x => x.Age);

            Console.ReadLine();
                   
        }


        public static void InputFor<T, TProp>(Expression<Func<T, TProp>> s)
        {
            Console.WriteLine(s.Body.ToString());
            Console.WriteLine(((MemberExpression)s.Body).Member.Name);
        }

        
    }

    public class Person
    {
        public string Lastname { get; set; }
        public int Age { get; set; }
    }

    public class HtmlHelper<T>
    {
    }

}

namespace Extensions
{
    public static class Helpers
    {
        public static void TextBoxFor<T,TProp>(this HtmlHelper<T> sx, Expression<Func<T, TProp>> s)
        {
            Console.WriteLine(s.Body.ToString());            
            Console.WriteLine(((MemberExpression)s.Body).Member.Name);
        }
    }

}



Output:
Extension method:
x.Lastname
Lastname
x.Age
Age

Non-extension method:
x.Lastname
Lastname
x.Age
Age


I'll use this proof-of-concept to make an HtmlHelper for jQuery AJAX ComboBox tomorrow

[UPDATE: March 24, 2011]

Good thing ASP.NET MVC is opensource, I was able to find the more robust way to generate an ID from strongly-typed model. The function resides in ExpressionHelper class, the function is GetExpressionText, which accepts a LambdaExpression.

So this:

namespace JqueryAjaxComboBoxHelper
{

    public static class InputExtensions
    {
        public static MvcHtmlString ComboBoxFor<TModel, TProperty>
            (this HtmlHelper<TModel> htmlHelper, 
             Expression<Func<TModel, TProperty>> expression)
        {

            // string fieldName = ((MemberExpression)expression.Body).Member.Name;

            string fieldName = ExpressionHelper.GetExpressionText(expression);

            var tagBuilder = new TagBuilder("div");
            tagBuilder.MergeAttribute("id", fieldName);
            tagBuilder.MergeAttribute("class", "ac_area");

            return new MvcHtmlString(tagBuilder.ToString());
        }
    }
}

And this:
Html.AjaxComboBoxFor(model => model.Address.City);

That will generate this:
<div class="ac_area" id="Address.City">


Whereas my proof-of-concept code (string fieldName = ((MemberExpression)expression.Body).Member.Name;) can only obtain City:

<div class="ac_area" id="City">

No comments:

Post a Comment