I have had to find a way to substitute implicit field references in a lambda expression with it’s real value. For example :
Expression<Func<TestObject, String>> exp = null;
for (int i = 0; i < 1; i++)
{
exp = t => t.SubObjs[i].TestSTR;
}
Func<TestObject, String> testFunc = exp.Compile();
String testValue = testFunc(myObj);
When inspecting the delegate, you can see this :
{t => t.SubObjs.get_Item(value(testExpression.Program+<>c__DisplayClass4).i).TestSTR}
When calling the delegate outside the for loop, the value of “i” is solved, by reference. But “i” have changed since it’s last iteration (“i” == 1 and not 0).
So I build a specific ExpressionVisitor in order to replace the corresponding node with a ConstantExpression :
public class ExpressionParameterSolver : ExpressionVisitor
{
protected override Expression VisitMember(MemberExpression node)
{
if (node.ToString().StartsWith("value(") && node.NodeType == ExpressionType.MemberAccess)
{
var index = Expression.Lambda(node).Compile().DynamicInvoke(null);
return Expression.Constant(index, index.GetType());
}
return base.VisitMember(node);
}
}
I don’t have found a way other than .StartsWith(“value(“) in order to detect that the current node is a reference to a field… this kind of node inherits from FieldExpression but this class is internal, and I’m not sure FieldExpression only encapsulate what I consider an “implicit field reference”.
So is there a way (an attribute or a method) to explicitly know that a MemberExpression node is an implicit field reference ???
Thanks in advance !!!
and thanks to this stakx post
Just fetch the
Memberproperty from the expression and see whether it’s aFieldInfo…If you only want it to be for cases where the class is compiler-generated you could use
There can be other reasons why a type might be compiler-generated though. It doesn’t sound like a terribly good idea to me.
Can’t you just avoid capturing loop variables in your lambda expressions to start with?