2016-05-24 10 views
0

outパラメータを持つメソッドを呼び出す式を作成しようとしています。これまではパラメータのnull可能なバージョンを除いて、成功しました。outパラメータとnull可能な型を使用した式の作成

この目的のために、int.TryParse(string, out int)メソッドを想定します。私は正常にこの目的のためにデリゲート型を定義することにより、式(なしnullables)を構築することができました:

internal delegate bool TestDelegate(string input, out int value);

public static MethodInfo GetMethod() 
{ 
    return typeof(int).GetMethod("TryParse", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string), typeof(int).MakeByRefType() }, null); 
} 

public static void NormalTestExpression() 
{ 
    var method = GetMethod(); 

    var pValue = Expression.Parameter(typeof(string), "str"); 
    var pOutput = Expression.Parameter(typeof(int).MakeByRefType(), "value"); 

    var call = Expression.Call(method, pValue, pOutput); 
    var lamd = Expression.Lambda<TestDelegate>(call, pValue, pOutput); 
    var func = lamd.Compile(); 

    int output; 
    var result = func("3", out output); 
    // THIS WORKS!!! 
} 

私がNULL可能タイプで、この作品を作るしようとしています。例えば取る:

internal delegate bool TestNullableDelegate(string input, out int? value);

以下の引数を除いて失敗する(GetMethod()は、プリミティブ型のオフに基づいて正しい方法を取得している - 上記と同じ方法)

public static void WithNullableTypeFails() 
{ 
    var method = GetMethod(); 

    var pValue = Expression.Parameter(typeof(string), "str"); 
    var pOutput = Expression.Parameter(typeof(int?).MakeByRefType(), "value"); 
value 
    var call = Expression.Call(method, pValue, pOutput); //Argument Exception int.TryParse() doesn't accept int? argument 

    var lamd = Expression.Lambda<TestNullableDelegate>(call, pValue, pOutput); 
    var func = lamd.Compile(); 

} 


Expression of type 'System.Nullable`1[System.Int32]' cannot be used for parameter of type 'System.Int32' of method 'Boolean TryParse(System.String, Int32 ByRef)' 

を今は私はまだプリミティブint型を取っているMethodInfoを呼び出していて、デリゲートは一致していないため、これが原因であることを認識しています。だから私は、以下試してみました:

public static void WithNullableTypeAttempt() 
{ 
    var method = GetMethod(); 

    var pValue = Expression.Parameter(typeof(string), "str"); 
    var pOutput = Expression.Parameter(typeof(int?).MakeByRefType(), "value"); 

    var vars = Expression.Variable(typeof(int), "tmp"); 
    var resultvar = Expression.Variable(typeof(bool), "result"); 

    var call = Expression.Call(method, pValue, vars); 
    var block = Expression.Block(
         Expression.Assign(vars, Expression.Constant(default(int))), 
         Expression.Assign(resultvar, call), 
         Expression.Assign(pOutput, Expression.Convert(vars, typeof(int?))), 
         resultvar 
       ); 
    var lamd = Expression.Lambda<TestNullableDelegate>(block, pValue, pOutput); 
    var func = lamd.Compile(); // Invalid Operation Exception 
} 

を、私はそれをコンパイルしようとしたとき、私は無効演算例外を取得:

variable 'tmp' of type 'System.Int32' referenced from scope '', but it is not defined 

私は私が持っている式ツリービジュアライザの一つで式を開いたとき、私は見ます次のようになります。

(valueToParse, value) => 
{ 
    var tmp = 0; 
    var result = int.TryParse(valueToParse, out tmp); 
    var value = (int?)tmp; 
    return result; 
} 

私は正しい道にいると思います。

Nullable型でデリゲートを保持し、Nullable型によってのみ型が異なるこのメソッドはどのように呼び出すことができますか?

答えて

2

現在、変数をサポートしていないoverload of the methodを使用しています。

は、上記の参照からの引用:

は、4つの式が含まれており、何の変数を持っていないBlockExpressionを作成します。あなたはこのようan overload that supports variablesを使用して、変数に関するブロックの表現を伝える必要があり

var block = Expression.Block(
        new ParameterExpression[] { vars, resultvar }, //variables 
        Expression.Assign(vars, Expression.Constant(default(int))), 
        Expression.Assign(resultvar, call), 
        Expression.Assign(pOutput, Expression.Convert(vars, typeof(int?))), 
        resultvar); 
+0

感謝。私はそれがIntelliSenseで過負荷になっているのを見たが、何も考えなかった。私はまだ表現を学んでいるので、本当に私に何も意味しなかった。これは私がこれを行うための最善の方法ですか、それとも他の方法ですか? (PS、会議では、少し試してみます) – pinkfloydx33

+0

あなたは大歓迎です。私は助けることができてうれしいです。 –

+0

私は 'TryParse'は単なる例であると仮定していますが、現実には、コンパイル時に自分自身が知られていないメソッドなのでしょうか? –

関連する問題