Click here to Skip to main content
15,879,184 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Say we have the following :
C#
        private static string Query<T>(Expression<Func<T, bool>> pr)
        {
            return pr.ToString();
        }
...
int ii = 1000;
string str = Query((SalesInvoiceRow r) => r.Serial > ii && r.CustomerName.Contains( "23"));

When you run the above we get:
r => ((r.Serial > value(testing.program+<>c__DisplayClass0).ii) AndAlso r.CustomerName.Contains("23"))

How can we get the value of ii instead of the ugly statement like below?
r => ((r.Serial > 1000) AndAlso r.CustomerName.Contains("23"))
Posted

Hello Mehdi,

This is some experimental code to tweak with the ExpressionVisitor:

C#
static void Main(string[] args)
{
    int a = 5;
    int b = 100;
    Expression<Func<int, bool>> expr = v => v > (a + b);
    WalkVisitor w = new WalkVisitor();
    w.Visit(expr);
}
public class WalkVisitor : ExpressionVisitor
{
    protected override Expression VisitMember(MemberExpression node)
    {
        var e = base.VisitMember(node);
        var c = node.Expression as ConstantExpression;
        if (c != null)
        {
            Type t = c.Value.GetType();
            var x = t.InvokeMember(node.Member.Name, BindingFlags.GetField,
                                   null, c.Value, null);
            Console.WriteLine("{0} = {1}", node.ToString(), x);
        }
        return e;
    }
}


The output is:

value(ExprVisitor.Program+<>c__DisplayClass0).a = 5
value(ExprVisitor.Program+<>c__DisplayClass0).b = 100


You might need to implement a print visitor around this snippet...

Cheers

Andi
 
Share this answer
 
Comments
Mehdi Gholam 1-Feb-12 14:34pm    
Nice! but ExpressionVistor is a pain to wrap your head around I have seen this but it's a ton of code [for those who don't know me - I hate tonnes of code :) ]

5'ed anyway
Andreas Gieriet 1-Feb-12 14:55pm    
Hello Mehdi,

Thanks for your 5!

So, we "suffer" the same ;-) "Less is often more!"

But I must admit: I like visitors for syntax traversing. Once you have the basic building blocks (traversing visitor, print visitor), additions and variations are usually tidy.

What is currently missing is the print visitor for the Expression syntax tree. Maybe I write an article about it if there is no such thing deeply buried somewhere of the web...

As for the troubles above: I suspect that the Value type of the ConstantExpression is wrong, at least for these lambda classes (DisplayClass...). I initially tried the VisitConstant() method, but there is no way to access the constant member of the class. Useless. So I had do analyze the call stack in the debugger and saw that the callee of the VisitConstant() was VisitMember().

Cheers

Andi
You should be able to compile the expression and then ToString it.

C#
pr.Compile().ToString();


[Edit]
I just realized you want ii. I am totally confused now. Aren't you setting ii to 1000? Why do you now want the value?
Maybe you meant you want the query resolved. Well you should do what I posted then, Compile :)
 
Share this answer
 
v3
Comments
Pete O'Hanlon 1-Feb-12 12:14pm    
This was the problem I had. I couldn't quite see what he was after. Mehdi's a smart guy so I reckon it's something really esoteric.
Mehdi Gholam 1-Feb-12 14:30pm    
Sorry Compile().ToString() gives : System.Func`2[testing.program+SalesInvoiceRow,System.Boolean]

What I am after is : ((r.Serial > 1000) AndAlso r.CustomerName.Contains("23")) where the ii is replaced with it's value not the ref to the variable.
[no name] 1-Feb-12 14:49pm    
OK I think I am starting to see what you are trying to do now. Never mind about the compile as it will execute it (I think we needed one more set of () though).
Yoru wording through me off. It sounded like you did not want the "Ugly statement bellow"... So I thought you were trying to execute the expression.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900