式はコンストラクタをパラメータで呼び出し、その値を設定します

c# constructor expression-trees lambda reflection

質問

私は、デフォルトのctorを使用する代わりに、式からパラメータ化されたコンストラクタを呼び出そうとしています。これはコンストラクタパラメータを取得するコードです:

ConstructorInfo ci = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, CallingConventions.HasThis, new[] { typeof(bool) }, new ParameterModifier[] { });
ParameterInfo[] paramsInfo = ci.GetParameters();

//create a single param of type object[]
ParameterExpression param = Expression.Parameter(typeof(bool), "il");

Expression[] argsExp = new Expression[paramsInfo.Length];

//pick each arg from the params array 
//and create a typed expression of them
for (int i = 0; i < paramsInfo.Length; i++)
{
    Expression index = Expression.Constant(i);
    Type paramType = paramsInfo[i].ParameterType;

    Expression paramAccessorExp = param;
    //Expression.ArrayIndex(param, index);

    Expression paramCastExp =
        Expression.Convert(paramAccessorExp, paramType);

    argsExp[i] = param;
}                  

NewExpression ci2 = Expression.New(ci, argsExp);

しかし、私はラムダ式をコンパイルしようとすると、私は次のエラーが表示されます:

スコープ ''から参照される 'System.Boolean'型の変数 'il'が定義されていません "

私は何が欠けていますか?どんな助けやヒントもありがとうございます。

受け入れられた回答

コードの4行目にliというパラメータを定義します。これをラムダ式で使用するには、このパラメータが定義されているスコープが必要です。あなたには2つの選択肢があります:

  1. paramをローカル変数として含むBlockExpressionを作成します。次に、この式をラムダ式の本体として使用します。
  2. LambdaExpressionパラメータとしてparamを使用します。

オプション1を使用する場合は、変数を初期化する必要もあります。そうしないと、別の種類のエラーメッセージが表示されます。

EDIT

投稿した追加コードには2つの問題があります:

  1. 式ツリー全体で同じパラメータオブジェクトを使用する必要があります。同じ名前と型を持つことによって、2つのParameterオブジェクトが等しくなることはありません。 param変数を再利用できるように、 ConvertThisメソッドへのラムダの作成まで、すべてを移動するだけです。 ConvertThisの戻り値をコンパイルしてデリゲートを取得することができます。

  2. BlockExpressionを作成するときは、 paramをローカル変数として渡す必要があります。これを行うには、 new ParameterExpression[] { param }という引数をメソッドに追加します。


人気のある回答

試す

ParameterExpression param = Expression.Parameter(typeof(bool); 



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ