Dot-Net
如何指定要從表達式樹方法返回的對象?
我正在嘗試使用返回對象的表達式樹創建一個方法,但我不知道如何實際指定要返回的對象。我試過閱讀這個,但實際上似乎沒有在任何地方指定返回值。
我已經完成了所有的分配和東西,但是如何指定要從使用表達式樹創建的方法返回的對象?
編輯:這些是 v4 表達式樹,我試圖創建的方法是這樣的:
private object ReadStruct(BinaryReader reader) { StructType obj = new StructType(); obj.Field1 = reader.ReadSomething(); obj.Field2 = reader.ReadSomething(); //...more... return obj; }
顯然 a
return是GotoExpression您可以使用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。