dynamic code generation in c#

Copied directly from ayende.com

Given a Dictionary<string, string>, convert that dictionary into a type in as performant a manner as possible. The conversion will happen many time, and first time costs are acceptable.

public static Func<Dictionary<string, string>, T> Generate<T>()
    where T : new()
{
    var dic = Expression.Parameter(typeof (Dictionary<string, string>), "dic");
    var tmpVal = Expression.Parameter(typeof (string), "tmp");
    var args = new List<MemberAssignment>();
    foreach (var propertyInfo in typeof(T).GetProperties())
    {
        var tryGet = Expression.Call(dic, "TryGetValue", new Type[0], 
            Expression.Constant(propertyInfo.Name),
            tmpVal);

        Expression value = tmpVal;
        if (propertyInfo.PropertyType != typeof (string))
        {
            var convertCall = Expression.Call(typeof(Convert).GetMethod("ChangeType", 
                new Type[] { typeof(object), typeof(Type) }), tmpVal,
                Expression.Constant(propertyInfo.PropertyType));
            value = Expression.Convert(convertCall, propertyInfo.PropertyType);
        }

        var conditional = Expression.Condition(tryGet, value, 
            Expression.Default(propertyInfo.PropertyType));

        args.Add(Expression.Bind(propertyInfo, conditional));

    }
    var newExpression = Expression.New(typeof(T).GetConstructor(new Type[0]));

    var expression = Expression.Lambda<Func<Dictionary<string, string>, T>>(
        Expression.Block(new[] { tmpVal },Expression.MemberInit(newExpression,args)),
        dic);

    return expression.Compile();
}

this code does is dynamically generate the following method

(Dictionary<string,string> dic) => {
    string tmp;
    return new User
    {
        Name = dic.TryGetValue("Name", out tmp) ? tmp : default(string),
        Age = dic.TryGetValue("Age", out tmp) ? (int)Convert.ChangeType(tmp, typeof(int)) : default(int)
    };
}

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.