如何创建动态Lambda表达式

3

我有一个问题,如何添加另一个筛选器并验证被选择的内容?

private Expression < Func < Entity.Modelos.Flux, bool >> Filter() {
    var dateStart = dtpDateStart.Value.Date;
    var dateEnd = dtpDateEnd.Value.Date;

    Expression < Func < Entity.Modelos.Flux, bool >> expr = null;

    expr = f = > f.DatFlux >= dateStart.Date && f.DatFlux <= dateEnd.Date;

    if (txtDescription.Text != String.Empty) {
        //add filter
    }

    return expr;
}

更新:我将在此函数中使用该表达式:
public virtual IQueryable < T > Filter(Expression < Func < T, bool >> expressao) {
    return DbSet.Where(expressao).AsQueryable < T > ();
}

我想要做的是使用一个表达式来完成这个任务。
public List < Users > GetUsers(int ? id, string name) {
    using(DBContext ctx = new DBContext()) {
        IQueryable query = ctx.Usuarios;
        if (id.HasValue)
            query = query.Where(x = > x.ID == id);

        if (!string.IsNullOrEmpty(name))
            query = query.Where(x = > x.Name.StartsWith(name));

        return query.ToList();

    }
}

2
请标记你使用的编程语言。 - j_mcnally
你是在说你正在尝试使用语句传回另一个表达式,还是试图嵌入lambda表达式?我不太明白你究竟想做什么。 - corylulu
我正在尝试嵌入Lambda表达式。 - davidterra
好的,如果是这样的话,那么我提供了一个嵌入式lambda语句的示例。但我不确定你期望什么样的返回值,所以我不知道你想如何修改你的示例。 - corylulu
我添加更新了如何使用的说明。 - davidterra
5个回答

0
如果这只是您需求的演示,那么您可以使用System.Linq.Expressions命名空间创建和修改表达式树
然而,在您的问题情况下,使用EF可能会更容易:
bool filterDescription = !String.IsNullOrEmpty( txtDescription.Text );

expr = f =>
  (
    ( f.DatFlux >= dateStart.Date && f.DatFlux <= dateEnd.Date )
    &&
    ( !filterDescription || ... add filter ... )
  )
;

或者普通的C#:

if ( String.IsNullOrEmpty( txtDescription.Text ) )
{
  expr = f => f.DatFlux >= dateStart.Date && f.DatFlux <= dateEnd.Date;
}
else
{
  expr = f => f.DatFlux >= dateStart.Date && f.DatFlux <= dateEnd.Date
    &&
    ... add filter ...
  ;
}

0

好的,这里是一个关于如何嵌入lambda语句的示例。虽然不是你的示例,但是给你:

Func<int, int, EventHandler> makeHandler =
    (dx, dy) => (sender, e) => {
        var btn = (Button) sender;
        btn.Top += dy;
        btn.Left += dx;
    };

btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);

0

尝试这种方式:

private Expression<Func<Entity.Modelos.Flux, bool>> Filter()
{
    var dateStart = dtpDateStart.Value.Date;
    var dateEnd = dtpDateEnd.Value.Date;

    Func<Entity.Modelos.Flux, bool> expr = null;

    expr = f => f.DatFlux >= dateStart.Date && f.DatFlux <= dateEnd.Date;

    if(txtDescription.Text != String.Empty)
    {
       expr = f => expr(f) && f.Title.Equals(txtDescription.Text); // ← Your additional filter
    }

    return f => expr(f);
}

获取错误:“LINQ表达式节点类型“Invoke”在LINQ到实体中不受支持”。 - davidterra

0

这很简单。访问此链接

棘手的事情是调用OrderByAlias - 使用MakeGenericMethod可能是一种方法,就像上面的链接中所示。


3
我不认为表达式树是“简单”的......(另外:我觉得这个回答可能应该是一条评论。) - Marc Gravell

0

继承自ExpressionVisitor

public class MyVisitor: ExpressionVisitor
{
    private LambdaExpression visitor;
    public Expression Modify(Expression expression, LambdaExpression visitor)
    {
        this.visitor = visitor;
        return Visit(expression);
    }

    protected override Expression VisitBinary(BinaryExpression b)
    {
        var binary = visitor.Body as BinaryExpression;

        return Expression.MakeBinary(ExpressionType.AndAlso, b, binary, b.IsLiftedToNull, b.Method);
    }
}

你的Filter()方法可能长这样

    private Expression<Func<Entity.Modelos.Flux, bool>> Filter()
    {
        var dateStart = dtpDateStart.Value.Date;
        var dateEnd = dtpDateEnd.Value.Date;
        var description = txtDescription.Text;

        Expression<Func<Entity.Modelos.Flux, bool>> expr = null;

        expr = f => f.DatFlux >= dateStart.Date && f.DatFlux <= dateEnd.Date;

        if (description != String.Empty)
        {
            //add filter
            Expression<Func<Entity.Modelos.Flux, bool>> other = f => f.Description == description;

            var modifier = new MyVisitor();
            expr = (Expression<Func<Entity.Modelos.Flux, bool>>)modifier.Modify((Expression)expr, (LambdaExpression)other);
        }

        return expr;
    }

示例

查看以下内容以获取更多信息

如何:修改表达式树(C# 和 Visual Basic)


返回错误 {"值不能为 null。\r\n参数名: right"} - davidterra
return Expression.MakeBinary(ExpressionType.AndAlso, b, binary, b.IsLiftedToNull, b.Method); - davidterra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接