【问题标题】:How can I create dynamic Lambda Expressions如何创建动态 Lambda 表达式
【发布时间】:2013-03-19 17:34:46
【问题描述】:

我有一个问题,如何添加另一个过滤器并且我必须验证它是否被选中?

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

    }
}

【问题讨论】:

  • 请用您的编程语言标记它。
  • 你是说你想用你的语句传回另一个表达式还是你想嵌入 lambda 表达式?我不完全了解您要做什么
  • 我正在尝试嵌入 lambda 表达式。
  • 好的,如果是这样,那么我提供了一个嵌入式 lambda 语句的示例。但我不确定你期望的返回值是什么,所以我不知道你想如何修改你的示例。
  • 我添加更新我将如何使用。

标签: c# expression lambda


【解决方案1】:

继承自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;
    }

example

查看以下内容了解更多信息

How to: Modify Expression Trees (C# and Visual Basic)

【讨论】:

  • 返回错误{"Value cannot be null.\r\nParameter name: right"}
  • return Expression.MakeBinary(ExpressionType.AndAlso, b, binary, b.IsLiftedToNull, b.Method);
【解决方案2】:

如果这只是您的需求演示,那么您可以使用System.Linq.Expressions 命名空间创建和修改Expression Trees

但是,就您的问题而言,使用 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 ...
  ;
}

【讨论】:

    【解决方案3】:

    好的,这里有一个关于如何嵌入 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);
    

    【讨论】:

      【解决方案4】:

      It is simple.Visit this link

      棘手的是调用OrderByAlias - 使用MakeGenericMethod 可能是一种方式,如上面的链接所示。

      【讨论】:

      • 我不会将表达式树归类为“简单”...(另外:这个答案可能应该是评论,IMO)
      【解决方案5】:

      试试这个方法:

      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 to Entities 不支持 LINQ 表达式节点类型 'Invoke'”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-18
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多