I'm trying to create a method using an expression tree that returns an object, but I can't figure out how to actually specify the object to return. I've tried reading this, but the return value doesn't actually seem to be specified anywhere.
I've got all the assignments & stuff down, but how do I specify the object to return from a method created using expression trees?
EDIT: these are v4 expression trees, and the method I'm trying to create does something like this:
private object ReadStruct(BinaryReader reader) {
StructType obj = new StructType();
obj.Field1 = reader.ReadSomething();
obj.Field2 = reader.ReadSomething();
//...more...
return obj;
}
There is a much easier way to do this in cases that return an existing parameter or variable. The last statement in a Block Expression becomes the return value. You can include the ParameterExpression again at the end to have it returned.
Assuming your struct is like this:
public struct StructType
{
public byte Field1;
public short Field2;
}
Then your code would look like this:
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();
Test that it works:
var stream = new MemoryStream(new byte[] {0x57, 0x46, 0x07});
var reader = new BinaryReader(stream);
var struct1 = ReadStruct(reader);
It's worth mentioning this example works if StructType is a struct. If it is a class, you just call the constructor and initialize structVar first thing in the BlockExpression.