表达力<>以评估本地变量(force Expression<> to evalua

2019-09-23 12:42发布

我在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;}
}

它输出

UD =>((ud.Date ==值(UserQuery + <> C_ DisplayClass0).t1)AndAlso(ud.Number ==值(UserQuery + <>Ç_DisplayClass0).n1))

是否有任何可能的方式来保持变量,但有它的输出是这样的:

关=>((== ud.Date解析( “1/10/2012”))andalso(ud.Number ==转换(1)))

Answer 1:

开始了; 输出第一:

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

这不会输出Parse(...)因为你的表情不包含解析:您已经评价,到时候你把它变成一个lambda。

还需要注意的是这个处理捕获的变量的一个水平。 对于更复杂的(嵌套)拍摄环境中,你将不得不递归从捕获类读取值:

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;}
}


Answer 2:

如果你都OK承担Microsoft的.NET Framework /在未来一段时间内打破 CoreFX的实现细节的依赖,看看什么是在下面的扰流板箱:

还有的Expression.DebugView财产 。 你需要做的是这样通过反射找到它。
它使用ExpressionVisitor实现的 ,像什么在做马克Gravell的回答这个问题。

我要再次强调这一点:这是私人财产。



文章来源: force Expression<> to evaluate local variables