4.0 では、ツリーでブロック操作がサポートされているため、これははるかに簡単です (ただし、C# 式コンパイラではサポートされていません)。
StringBuilder
ただし、 「流れるような」API を公開するという事実を利用することで、これを行うことができます。その代わりに、以下のようAction<T,StringBuilder>
なFunc<T,StringBuilder,StringBuilder>
- があります (この場合、これらの式を表現するための実際の構文は同じであることに注意してください):
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();
// now test it
StringBuilder sbInst = new StringBuilder();
func(val, sbInst);
Console.WriteLine(sbInst.ToString());
}
}
public class MyType : IMyType
{
public string Name { get; set; }
public string Description { get; set; }
}
interface IMyType
{
string Name { get; }
string Description { get; }
}
ツリーを調べて IL を手動で発行することは確かに可能DynamicMethod
ですが (おそらく)、複雑さを制限することについていくつかの決定を下す必要があります。提示されたコードについては、妥当な時間で実行できますが(まだ簡単ではありません)、より複雑なものを期待する場合Expression
は、揚げ物になります。