In 4.0, this is much simpler thanks to the support of block operations in the tree (although not in the C # expression compiler).
However, you can do this using the fact that StringBuilder provides a "free" API; so instead of Action<T,StringBuilder> you have Func<T,StringBuilder,StringBuilder> - as shown below (note that the actual syntax of the expression of these expressions is identical in this case):
class Program { static void Main() { Foo(new MyType { Name = "abc", Description = "def" }); } static void Foo<T>(T val) where T : IMyType { var expressions = new Expression<Func<T, StringBuilder, StringBuilder>>[] { (t, sb) => sb.Append(t.Name), (t, sb) => sb.Append(", "), (t, sb) => sb.Append(t.Description) }; var tparam = Expression.Parameter(typeof(T), "t"); var sbparam = Expression.Parameter(typeof(StringBuilder), "sb"); Expression body = sbparam; for (int i = 0; i < expressions.Length; i++) { body = Expression.Invoke(expressions[i], tparam, body); } var func = Expression.Lambda<Func<T, StringBuilder, StringBuilder>>( body, tparam, sbparam).Compile();
Of course, you can check the trees and emit IL manually (perhaps DynamicMethod ), but you will need to make some decisions about limiting complexity. For the code presented, I could do it in a reasonable amount of time (still not trivial), but if you expect something more complicated Expression more you are fried.
Marc gravell
source share