2011-02-07 4 views
15

オブジェクトを返す式ツリーを使用してメソッドを作成しようとしていますが、実際に返すオブジェクトを指定する方法がわかりません。私はthisを読んでみましたが、戻り値は実際にはどこにも指定されていないようです。式ツリーメソッドから返すオブジェクトを指定するにはどうすればよいですか?

私は&ものダウンすべての割り当てを持っているが、どのように私は、式ツリーを使用して作成したメソッドから返されるオブジェクトを指定するのですか?

EDIT:これらはv4の式ツリーであり、私が作成しようとしている方法は、このようなものはない:どうやらreturnあなたはExpression.Returnファクトリメソッドを使用して作成することができますGotoExpression

private object ReadStruct(BinaryReader reader) { 
    StructType obj = new StructType(); 
    obj.Field1 = reader.ReadSomething(); 
    obj.Field2 = reader.ReadSomething(); 
    //...more... 
    return obj; 
} 
+0

これは実際に違いがあるので、これらのv3またはv4の表現ツリーですか?また、ツリーで表現しようとしているコードの例を表示できますか? –

+0

v4の表現ツリー。コードを追加するように編集しました。 – thecoop

答えて

18

です。あなたはそれにジャンプするには、最後にラベルを作成する必要があります。このような何か:

// an expression representing the obj variable 
ParameterExpression objExpression = ...; 

LabelTarget returnTarget = Expression.Label(typeof(StructType)); 

GotoExpression returnExpression = Expression.Return(returnTarget, 
    objExpression, typeof(StructType)); 

LabelExpression returnLabel = Expression.Label(returnTarget, defaultValue); 

BlockExpression block = Expression.Block(
    /* ... variables, all the other lines and... */, 
    returnExpression, 
    returnLabel); 

ラベル対象と後藤式の型が一致している必要があります。ラベルターゲットには型があるため、ラベル式にはデフォルト値が必要です。

+1

'label'引数はどこにポイントしますか? – thecoop

+2

@thecoop:他のものを変更しなければならなかったが、うまくいった。これは確かに仕事に苦労しています! –

+2

ああ、それは動作します。なぜそれがそんなに巻き込まれたのか? – thecoop

11

Iは式から値を返すことは、単に問題の値に対応するパラメータ表現とブロックを締結することによって行うことができることを意味源(ある場合)または実際の状態(別のケース)のカップルを発見しましたブロックからの最後に評価された式はその戻り値になるからです。報告されるように、Expression.Returnファクトリは、コードブロックの途中から返されるより複雑なケースに対して存在します。言い換えれば

あなたのブロック内の最後の式は、単にobjExpressionであれば、それは十分なはずです。私は、Returnメソッドとラベルを使ってすべてのビジネスを解体すれば、objExpressionは基本的に(ブロックの最後の)ラベルに渡され、returnExpressionを排除した場合と同じように残ることになりますreturnLabelとobjExpressionで単純に結びついています。

は残念ながら、私は実際にこれを自分でテストする立場にないです。

+4

.NET 4.5で検証済み – bugventure

+0

は.NETで動作します。4.ブロック式の最後に 'Expression.Constant(null)'だけでもnullを返します。 –

22

既存のパラメータまたは変数を返す場合にこれを行う方がはるかに簡単です。ブロック式の最後のステートメントが戻り値になります。 ParameterExpressionを最後に含めて、返すことができます。

public struct StructType 
{ 
    public byte Field1; 
    public short Field2; 
} 

次に、あなたのコードは次のようになります:それが動作することを

var readerType = typeof(BinaryReader); 
var structType = typeof(StructType); 
var readerParam = Expression.Parameter(readerType); 
var structVar = Expression.Variable(structType); 

var expressions = new List<Expression>(); 

expressions.Add(
    Expression.Assign(
     Expression.MakeMemberAccess(structVar, structType.GetField("Field1")), 
     Expression.Call(readerParam, readerType.GetMethod("ReadByte")) 
     ) 
    ); 

expressions.Add(
    Expression.Assign(
     Expression.MakeMemberAccess(structVar, structType.GetField("Field2")), 
     Expression.Call(readerParam, readerType.GetMethod("ReadInt16")) 
     ) 
    ); 

expressions.Add(structVar); //This is the key. This will be the return value. 

var ReadStruct = Expression.Lambda<Func<BinaryReader, StructType>>(
    Expression.Block(new[] {structVar}, expressions), 
    readerParam).Compile(); 

テスト:あなたの構造体を仮定し

はこのようなものです

var stream = new MemoryStream(new byte[] {0x57, 0x46, 0x07}); 
var reader = new BinaryReader(stream); 
var struct1 = ReadStruct(reader); 

それは、この例を言及する価値がありますStructTypeが構造体の場合に機能します。クラスの場合は、コンストラクタを呼び出して、BlockExpressionのstructVarを最初に初期化します。

関連する問題