Originally posted on: http://geekswithblogs.net/Nettuce/archive/2013/02/20/arguments-to-dto-parser-for-console-applications.aspx
public static class ArgumentParser<T> where T : new() { delegate bool TryParseFunc<TProperty>(string input, out TProperty output); public static T Parse(string[] args, params Expression<Func<T, object>>[] propertiesToSet) { var target = new T(); var propertyList = propertiesToSet.ToList(); foreach (var property in propertyList) { var propertyName = PropertyName(property); var arg = args[propertyList.IndexOf(property)]; var returnType = typeof(T).GetProperty(propertyName).PropertyType; var methodType = Nullable.GetUnderlyingType(returnType) ?? returnType; var stringParameter = Expression.Parameter(typeof(string)); var outParameter = Expression.Parameter(methodType.MakeByRefType()); var parseExpression = Expression.Call(methodType.GetMethods().Single(x => x.Name == "TryParse" && x.GetParameters().Count() == 2), stringParameter, outParameter); var tryParseFunc = typeof(ArgumentParser<T>).GetMethod("InvokeTryParseFunc", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(methodType).Invoke(null, new object[] { arg, parseExpression, stringParameter, outParameter }) as Tuple<bool, object>; if (!tryParseFunc.Item1) continue; var targetParameter = Expression.Parameter(typeof(T)); var memberParameter = Expression.Parameter(returnType); var member = Expression.PropertyOrField(targetParameter, propertyName); var assign = Expression.Assign(member, memberParameter); Expression.Lambda(assign, targetParameter, memberParameter).Compile().DynamicInvoke(target, tryParseFunc.Item2); } return target; } static Tuple<bool, object> InvokeTryParseFunc<TProperty>(string arg, MethodCallExpression parseExpression, ParameterExpression stringParameter, ParameterExpression outParameter) { TProperty value; var result = Expression.Lambda<TryParseFunc<TProperty>>(parseExpression, stringParameter, outParameter).Compile().Invoke(arg, out value); return new Tuple<bool, object>(result, value); } static string PropertyName(LambdaExpression propertyExpression) { return (propertyExpression.Body is UnaryExpression ? (MemberExpression)((UnaryExpression)propertyExpression.Body).Operand : (MemberExpression)propertyExpression.Body).Member.Name; } }