Dot-Net

如何指定要從表達式樹方法返回的對象?

  • February 7, 2011

我正在嘗試使用返回對象的表達式樹創建一個方法,但我不知道如何實際指定要返回的對象。我試過閱讀這個,但實際上似乎沒有在任何地方指定返回值。

我已經完成了所有的分配和東西,但是如何指定要從使用表達式樹創建的方法返回的對象?

編輯:這些是 v4 表達式樹,我試圖創建的方法是這樣的:

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

顯然 areturnGotoExpression您可以使用Expression.Return工廠方法創建的。您需要在最後創建一個標籤才能跳轉到它。像這樣的東西:

// 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);

標籤目標和 goto 表達式的類型必須匹配。因為標籤目標有一個類型,所以標籤表達式必須有一個預設值。

在返回現有參數或變數的情況下,有一種更簡單的方法可以做到這一點。塊表達式中的最後一條語句成為返回值。您可以在最後再次包含 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。

引用自:https://stackoverflow.com/questions/4924312