C# 从二进制表达式到表达式<;Func<;T、 布尔>&燃气轮机;

C# 从二进制表达式到表达式<;Func<;T、 布尔>&燃气轮机;,c#,linq-to-entities,C#,Linq To Entities,假设我有 Expression<Func<SomeType, DateTime>> left = x => x.SomeDateProperty; Expression<Func<SomeType, DateTime>> right = x => dateTimeConstant; var binaryExpression = Expression.GreaterThan(left, right); Expression<Func

假设我有

Expression<Func<SomeType, DateTime>> left = x => x.SomeDateProperty;
Expression<Func<SomeType, DateTime>> right = x => dateTimeConstant;
var binaryExpression = Expression.GreaterThan(left, right);
Expression<Func<SomeType, bool>> predicate = 
                          x => x.SomeDateProperty> dateTimeConstant;
表达式left=x=>x.SomeDateProperty; 表达式right=x=>dateTimeConstant; var binaryExpression=Expression.GreaterThan(左、右); 表达式谓词= x=>x.SomeDateProperty>dateTimeConstant; 1) 如何将最后一行赋值的右侧替换为使用
binaryExpression
的内容<代码>变量谓词=x=>二进制表达式不起作用

2) 右侧的
总是一个常量,不一定是DateTime.Now。它可能是某种更简单的
表达式
类型吗?例如,它不依赖于某个类型,它只是一个常量

3) 如果我将
大于
作为
字符串
,是否有办法从该字符串到
表达式中同名的方法?通常,如果比较方法的名称以
字符串的形式给出,那么如何从字符串开始实际调用
表达式
类上同名的方法


如果有必要,它必须与LINQ to实体一起工作。

1和2:您需要手动构建表达式树来完成此操作,编译器无法提供帮助,因为它只构造表示整个函数的现成表达式。当您想要逐段构建函数时,这是没有用的

以下是构建所需表达式的一种简单方法:

var argument = Expression.Parameter(typeof(SomeType));
var left = Expression.Property(argument, "SomeDateProperty");
var right = Expression.Constant(DateTime.Now);

var predicate = Expression.Lambda<Func<SomeType, bool>>(
    Expression.GreaterThan(left, right),
    new[] { argument }
);
3:由于二元谓词的可能选择数量很小,因此可以使用字典:

var wordToExpression = 
    new Dictionary<string, Func<Expression, Expression, BinaryExpression>>
{
    { "GreaterThan", Expression.GreaterThan },
    // etc
};
var wordToExpression=
新词典
{
{“GreaterThan”,表达式.GreaterThan},
//等
};
然后,在第一个代码片段中,您将执行类似于
wordToExpression[“GreaterThan”](左、右)
的操作,而不是硬编码
Expression.GreaterThan


当然,这也可以通过反射的标准方式来完成。

当您使用大于
的表达式时,您需要指定表达式体,而不是lambda本身。不幸的是,有一个复杂问题:两个表达式中的
x
不相同

在这个特殊的情况下,您可以侥幸逃脱,因为第二个表达式没有使用
x

所以,;您的“1”和“2”应回答为:

var binaryExpression = Expression.GreaterThan(left.Body, right.Body);
    var lambda = Expression.Lambda<Func<SomeType, bool>>(binaryExpression,
        left.Parameters);
为你的“3”;这并不是天生的;不过,您可以使用反射:

string method = "GreaterThan";

var op = typeof(Expression).GetMethod(method,
    BindingFlags.Public | BindingFlags.Static,
    null, new[] { typeof(Expression), typeof(Expression) }, null);

var rightBody = new SwapVisitor(right.Parameters[0],
     left.Parameters[0]).Visit(right.Body);
var exp = (Expression)op.Invoke(null, new object[] { left.Body, rightBody });

var lambda = Expression.Lambda<Func<SomeType, bool>>(exp, left.Parameters);
string method=“GreaterThan”;
var op=typeof(表达式).GetMethod(方法,
BindingFlags.Public | BindingFlags.Static,
null,新[]{typeof(表达式),typeof(表达式)},null);
var rightBody=new SwapVisitor(右参数[0],
左。参数[0])。访问(右。正文);
var exp=(表达式)op.Invoke(null,新对象[]{left.Body,rightBody});
var lambda=Expression.lambda(exp,left.Parameters);

您可以使用ExpressionVisitor类更改表达式树。
var binaryExpression = Expression.GreaterThan(left.Body,
    new SwapVisitor(right.Parameters[0], left.Parameters[0]).Visit(right.Body));
var lambda = Expression.Lambda<Func<SomeType, bool>>(binaryExpression,
    left.Parameters);
public class SwapVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public SwapVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}
string method = "GreaterThan";

var op = typeof(Expression).GetMethod(method,
    BindingFlags.Public | BindingFlags.Static,
    null, new[] { typeof(Expression), typeof(Expression) }, null);

var rightBody = new SwapVisitor(right.Parameters[0],
     left.Parameters[0]).Visit(right.Body);
var exp = (Expression)op.Invoke(null, new object[] { left.Body, rightBody });

var lambda = Expression.Lambda<Func<SomeType, bool>>(exp, left.Parameters);