序章
私のアプリケーションは、メソッドチェーンを使用してオブジェクトをインスタンス化するため、次のように生成および構成されます。
var car = new Car("Ferrari").Doors(2).OtherProperties(x = x.Color("Red"));
問題
実行時にこのオブジェクトを動的に生成する必要があります。構成に必要な連鎖メソッドは実行時に決定されるため、すべてをその場で動的にアセンブルする必要があります。私は過去にリフレクションを使用して次のような単純なオブジェクトを作成しましたnew Car("Ferrari", 2, "Red")
が、ラムダ式をパラメーターとして含むチェーンメソッドを使用したことはありません. 私は式ツリーを調べましたが、これは動的な式パラメーターを作成するためのソリューションの一部であると信じていますが、それをリフレクションと組み合わせて基本オブジェクトと追加の連鎖メソッドを作成する方法を見つけようとして完全に行き詰まっています。
感謝と感謝
時間を割いて私の問題を調べ、あなたが提供できるかもしれないガイダンスや情報について事前に.
更新: 結論
dasblinkenlight と Jon Skeet の回答に感謝します。dasblinkenlight の回答を選んだのは、彼のコード サンプルを見てすぐに実行できるようになったからです。Invoke()
メソッドチェーンについては、基本的に受け入れられた回答で同じループアプローチを使用したため、そのコードは繰り返しませんが、以下は式ツリーメソッド呼び出しをアクションデリゲートに動的に変換するために書いたコードであり、次に概説されているようにリフレクションを介して実行できますdasblinkenlightの答え。ジョンが指摘したように、これが本当に問題の核心でした。
メソッドのメタデータを格納するヘルパー クラス。
public struct Argument
{
public string TypeName;
public object Value;
}
public class ExpressionTreeMethodCall
{
public string MethodName { get; set; }
public IList<Argument> Arguments { get; set; }
public ExpressionTreeMethodCall()
{
Arguments = new List<Argument>();
}
}
ラムダ式メソッド呼び出しをアセンブルし、それを別の場所で実行されるアクション デリゲートとして返す静的メソッド (私の場合は引数として渡されますInvoke()
)。
public static Action<T> ConvertExpressionTreeMethodToDelegate<T>(ExpressionTreeMethodCall methodData)
{
ParameterExpression type = Expression.Parameter(typeof(T));
var arguments = new List<ConstantExpression>();
var argumentTypes = new List<Type>();
foreach (var a in methodData.Arguments)
{
arguments.Add(Expression.Constant(a.Value));
argumentTypes.Add(Type.GetType(a.TypeName));
}
// Creating an expression for the method call and specifying its parameter.
MethodCallExpression methodCall = Expression.Call(type, typeof(T).GetMethod(methodData.MethodName, argumentTypes.ToArray()), arguments);
return Expression.Lambda<Action<T>>(methodCall, new[] { type }).Compile();
}