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 Member
property from the expression and see whether it's a FieldInfo
...
If you only want it to be for cases where the class is compiler-generated you could use
if (expression.Member is FieldInfo &&
expression.Member
.DeclaringType
.IsDefined(typeof(CompilerGeneratedAttribute), false))
{
....
}
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?
精彩评论