力前pression<>以评估本地变量 [英] force Expression<> to evaluate local variables

查看:148
本文介绍了力前pression<>以评估本地变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的事情在LinqPad

 无效的主要()
{
    变种T1 = DateTimeOffset.Parse(2012年10月1日);

    诠释? N1 = 1;

    防爆pression< Func键<样品,布尔>> X1 = UD =>
        (ud.Date == T1&功放;&安培; ud.Number == N1);

    x1.ToString()转储()。
}

类样品
{
    公众诠释?数{设置;获得;}
    公众的DateTimeOffset日期{设置;获得;}
}
 

它输出

  

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

也可把这些变量,但有它的输出是这样的任何可能的方式:

  

UD =>((ud.Date ==解析(2012年10月1号))AndAlso(ud.Number ==   转换(1)))

解决方案

在这里,我们走;输出第一:

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

这永远不会输出解析(...),因为你的前pression的不包含的解析:你已经评估,到时候你把它变成一个lambda。

请注意,该处理捕获的变量的一个级别。对于更复杂的(嵌套)捕捉环境中,你必须递归从捕获类取值:

 使用系统;
使用System.Linq.Ex pressions;
使用的System.Reflection;
使用System.Runtime.CompilerServices;
静态类节目
{
    静态无效的主要()
    {
        变种T1 = DateTimeOffset.Parse(2012年10月1日);

        诠释? N1 = 1;

        防爆pression< Func键<样品,布尔>> X1 = UD =>
            (ud.Date == T1&功放;&安培; ud.Number == N1);

        VAR消毒=(出pression< Func键<样品,布尔>>)
            新Literalizer()访问(X1)。

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

类Literalizer:防爆pressionVisitor
{
    保护覆盖防爆pression VisitMember(MemberEx pression节点)
    {
        如果(node.Member.DeclaringType.IsDefined(typeof运算(CompilerGeneratedAttribute),FALSE)
            &功放;&安培; node.Ex pression.NodeType ==前pressionType.Constant)
        {
            对象目标=((ConstantEx pression)node.Ex pression)。价值,价值;
            开关(node.Member.MemberType)
            {
                案例MemberTypes.Property:
                    值=((的PropertyInfo)node.Member).GetValue(目标,NULL);
                    打破;
                案例MemberTypes.Field:
                    值=((字段信息)node.Member).GetValue(目标);
                    打破;
                默认:
                    值=目标= NULL;
                    打破;
            }
            如果(目标!= NULL)返回前pression.Constant(价值node.Type);
        }
        返回base.VisitMember(节点);
    }
}

类样品
{
    公众诠释?数{设置;获得;}
    公众的DateTimeOffset日期{设置;获得;}
}
 

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)))

解决方案

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

这篇关于力前pression&LT;&GT;以评估本地变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆