force Expression<> to evaluate local variables

.net, c#, expression-trees, lambda

Solution

Here we go; output first:

ud => ((ud.Date == 10/01/2012 00:00:00 +00:00) AndAlso (ud.Number == 1))

This will never output `Parse(...)`, because your expression does not contain a parse: you have already evaluated that by the time you put it into a lambda.

Note also that this handles one level of captured variable. For more complex (nested) capture contexts, you'll have to recursively fetch the values from the capture classes:

using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
static class Program
{
    static void Main()
    {
        var t1 = DateTimeOffset.Parse("10/1/2012");

        int? n1 = 1;

        Expression<Func<Sample, bool>> x1 = ud =>
            (ud.Date == t1 && ud.Number == n1);

        var sanitized = (Expression<Func<Sample, bool>>)
            new Literalizer().Visit(x1);

        Console.WriteLine(sanitized.ToString());
    }
}

class Literalizer : ExpressionVisitor
{
    protected override Expression VisitMember(MemberExpression node)
    {
        if(node.Member.DeclaringType.IsDefined(typeof(CompilerGeneratedAttribute), false)
            && node.Expression.NodeType == ExpressionType.Constant)
        {
            object target = ((ConstantExpression)node.Expression).Value, value;
            switch (node.Member.MemberType)
            {
                case MemberTypes.Property:
                    value = ((PropertyInfo)node.Member).GetValue(target, null);
                    break;
                case MemberTypes.Field:
                    value = ((FieldInfo)node.Member).GetValue(target);
                    break;
                default:
                    value = target = null;
                    break;
            }
            if (target != null) return Expression.Constant(value, node.Type);
        }
        return base.VisitMember(node);
    }
}

class Sample
{
    public int? Number{set;get;}
    public DateTimeOffset Date{set;get;}
}

Problem

I have something like this in LinqPad ``` void Main() { var t1 = DateTimeOffset.Parse("10/1/2012"); int? n1 = 1; Expression<Func<Sample,bool>> x1 = ud => (ud.Date == t1 && ud.Number == n1); x1.ToString().Dump(); } class Sample { public int? Number{set;get;} public DateTimeOffset Date{set;get;} } ``` it outputs ud => ((ud.Date == value(UserQuery+<>c_DisplayClass0).t1) AndAlso (ud.Number == value(UserQuery+<>c_DisplayClass0).n1)) is there any possible way to keep the variables but have it output something like this: ud => ((ud.Date == Parse("10/1/2012")) AndAlso (ud.Number == Convert(1)))

Original source