Home > Software design >  Get the value passed inside of a C# Expression value
Get the value passed inside of a C# Expression value

Time:01-31

I have the below class

public class TestClass
{
    public int TestProperty { get; set; }
}

I have the below code

int x = 1;
Expression<Func<TestClass, bool>> predicate = c => c.TestProperty == x;
Console.WriteLine(predicate.ToString());

The predicate.ToString() is returning c => (c.TestProperty == value(Program <>c__DisplayClass0_0).x)

Is there any way to evaluate the Expression in order to return c => (c.TestProperty == 1)

Note that it is not possible to create the expression with the value of x set as shown below

Expression<Func<TestClass, bool>> predicate = c => c.TestProperty == 1;

CodePudding user response:

It is not very easy and robust (relies on current expression generation patterns) but can be achieved with visitor:

class MySimpleConstantReplacingVisitor : ExpressionVisitor
{
    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Expression is ConstantExpression ce && node.Member is FieldInfo fe) // possibly check as PropertyInfo JIC
        {
            return Expression.Constant(fe.GetValue(ce.Value));
        }

        return base.VisitMember(node);
    }
}

And usage:

int xx = 1;
Expression<Func<TestClass, bool>> predicate = c => c.TestProperty == xx;
var modifiedExpression = new MySimpleConstantReplacingVisitor().Visit(predicate);
Console.WriteLine(modifiedExpression.ToString()); // prints "c => (c.TestProperty == 1)"

Note that this covers only simple cases (like the one in the example) and potentially there could be a lot of caveats. I don't know if there are libraries which do exactly what you need but there is quite a lot of libraries which handle analyzing the expression trees. Like almost every LINQ-based ORM - for example EF Core (see ParameterExtractingExpressionVisitor for example, check for closure part can be interesting). Or Serialize.Linq library.

  • Related