开发者

How to recognize a Lambda MemberExpression of type "field reference"

开发者 https://www.devze.com 2023-03-18 06:37 出处:网络
I have had to find a way to substitute implicit field references in a lambda expression with it\'s real value. For example :

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?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号