C# 如何动态创建表达式<;Func<;MyClass,bool>&燃气轮机;谓语

C# 如何动态创建表达式<;Func<;MyClass,bool>&燃气轮机;谓语,c#,linq,lambda,expression-trees,C#,Linq,Lambda,Expression Trees,我如何使用表达式树动态创建一个类似于 (p.Length== 5) && (p.SomeOtherProperty == "hello") 这样我就可以将谓词粘贴到lambda表达式中,就像这样 q.Where(myDynamicExpression)... 我只需要被指向正确的方向 更新:对不起,伙计们,我忽略了一个事实,即我希望谓词具有如上所述的多个条件。很抱歉造成混淆。原件 像这样: var param = Expression.Parameter(typeo

我如何使用表达式树动态创建一个类似于

(p.Length== 5) && (p.SomeOtherProperty == "hello") 
这样我就可以将谓词粘贴到lambda表达式中,就像这样

q.Where(myDynamicExpression)...
我只需要被指向正确的方向


更新:对不起,伙计们,我忽略了一个事实,即我希望谓词具有如上所述的多个条件。很抱歉造成混淆。

原件

像这样:

    var param = Expression.Parameter(typeof(string), "p");
    var len = Expression.PropertyOrField(param, "Length");
    var body = Expression.Equal(
        len, Expression.Constant(5));

    var lambda = Expression.Lambda<Func<string, bool>>(
        body, param);

要使用
&&
运算符组合多个谓词,可以一次将它们连接在一起

因此,如果您有一个名为
谓词的表达式对象列表,请执行以下操作:

Expression combined = predicates.Aggregate((l, r) => Expression.AndAlso(l, r));

使用谓词生成器


这很容易

要将Lambda表达式相互关联: 另一种方法是使用以下代码。在我的建议中,它比Schotime的答案更灵活,而且工作得很完美。不需要外部熔核

框架4.0

    // Usage first.Compose(second, Expression.And)
    public static Expression<T> Compose<T>(this Expression<T> First, Expression<T> Second, Func<Expression, Expression, Expression> Merge)
    {
        // build parameter map (from parameters of second to parameters of first)
        Dictionary<ParameterExpression,ParameterExpression> map = First.Parameters.Select((f, i) => new { f, s = Second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);

        // replace parameters in the second lambda expression with parameters from the first
        Expression secondBody = ParameterRebinder.ReplaceParameters(map, Second.Body);

        // apply composition of lambda expression bodies to parameters from the first expression 
        return Expression.Lambda<T>(Merge(First.Body, secondBody), First.Parameters);
    }

    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> First, Expression<Func<T, bool>> Second)
    {
        return First.Compose(Second, Expression.And);
    }

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> First, Expression<Func<T, bool>> second)
    {
        return First.Compose(second, Expression.Or);
    }


public class ParameterRebinder : ExpressionVisitor
{
    private readonly Dictionary<ParameterExpression, ParameterExpression> map;

    public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
    {
        this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
    }

    public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
    {
        return new ParameterRebinder(map).Visit(exp);
    }

    protected override Expression VisitParameter(ParameterExpression p)
    {
        ParameterExpression replacement;
        if (map.TryGetValue(p, out replacement))
        {
            p = replacement;
        }
        return base.VisitParameter(p);
    }
}
//用法第一。组合(第二,表达式。和)
公共静态表达式组合(此表达式优先,表达式第二,Func合并)
{
//构建参数映射(从第二个参数到第一个参数)
Dictionary map=First.Parameters.Select((f,i)=>new{f,s=Second.Parameters[i]});
//用第一个lambda表达式中的参数替换第二个lambda表达式中的参数
表达式secondBody=ParameterRebinder.ReplaceParameters(映射,Second.Body);
//将lambda表达式体的组合应用于第一个表达式中的参数
返回表达式.Lambda(Merge(First.Body,secondBody),First.Parameters);
}
公共静态表达式和(第一个表达式,第二个表达式)
{
首先返回。编写(第二,表达式。和);
}
公共静态表达式或(第一个表达式,第二个表达式)
{
首先返回.Compose(第二个,表达式.Or);
}
公共类参数Rebinder:ExpressionVisitor
{
私有只读字典映射;
公共参数索引(字典映射)
{
this.map=map??新建字典();
}
公共静态表达式替换参数(字典映射、表达式表达式)
{
返回新参数浏览器(map)。访问(exp);
}
受保护的重写表达式VisitParameter(ParameterExpression p)
{
参数表达替换;
if(映射TryGetValue(p,输出替换))
{
p=替换;
}
返回基访问参数(p);
}
}

我有一个名为的开源项目,它提供了创建动态谓词的非常简单的方法:

根据您的示例:

var exp1 = ExpressionBuilder.CreateBinary<YourClass>("MyProperty.Length", 5, ExpressionOperator.Equals);

var exp2 = ExpressionBuilder.CreateBinary<YourClass>("SomeOtherProperty", "hello", ExpressionOperator.Equals);

var fullExp = exp1.And(exp2);

// Use it normally...
q.Where(fullExp)
var exp1 = ExpressionBuilder.CreateBinaryFromQuery<YourClass>("eq('MyProperty.Length', '5')");

var exp2 = ExpressionBuilder.CreateBinaryFromQuery<YourClass>("eq('SomeOtherProperty', 'hello')");

var fullExp = exp1.And(exp2);

// Use it normally...
q.Where(fullExp)
var exp1=ExpressionBuilder.CreateBinary(“MyProperty.Length”,5,ExpressionOperator.Equals);
var exp2=ExpressionBuilder.CreateBinary(“SomeOtherProperty”,“hello”,ExpressionOperator.Equals);
var fullExp=exp1和(exp2);
//正常使用它。。。
q、 Where(fullExp)
它甚至支持全文谓词生成,因此您可以从HTTP GET方法接收任何动态查询,例如:

var exp1 = ExpressionBuilder.CreateBinary<YourClass>("MyProperty.Length", 5, ExpressionOperator.Equals);

var exp2 = ExpressionBuilder.CreateBinary<YourClass>("SomeOtherProperty", "hello", ExpressionOperator.Equals);

var fullExp = exp1.And(exp2);

// Use it normally...
q.Where(fullExp)
var exp1 = ExpressionBuilder.CreateBinaryFromQuery<YourClass>("eq('MyProperty.Length', '5')");

var exp2 = ExpressionBuilder.CreateBinaryFromQuery<YourClass>("eq('SomeOtherProperty', 'hello')");

var fullExp = exp1.And(exp2);

// Use it normally...
q.Where(fullExp)
var exp1=ExpressionBuilder.CreateBinaryFromQuery(“eq('MyProperty.Length','5'));
var exp2=ExpressionBuilder.CreateBinaryFromQuery(“eq('SomeOtherProperty','hello'));
var fullExp=exp1和(exp2);
//正常使用它。。。
q、 Where(fullExp)
它支持更多的数据类型和运算符


Link:

谢谢,但我愚蠢地忘了提到我希望谓词读作。。。(p.Length==5)和&(p.SomeOtherProperty==hello)。换言之,我如何链接条件?很抱歉没有说清楚,非常感谢您的更新。似乎就是我要找的。Thanks@MarkGravell:如果我们没有
SomeType
如何创建lambda。e、 g:我们只有Type
TyepOfEntity=Assembly.GetType(string.Format(“Smartiz.Data.{0}”,EntityName))
@Mohammad然后使用“object”并在表达式中包含类型转换步骤。不是在计算机上,但它将是Expression.Cast或Expression.Convert或Expression.ChangeType或类似的