【问题标题】:Combining expressions to return one expression for query组合表达式返回一个表达式进行查询
【发布时间】:2017-06-11 17:36:57
【问题描述】:

Expression<> 遇到了一点问题。

是否可以将两个以上的表达式合并为一个? 示例:

Expression<Func<Event, bool>> searchForLogCorrelationKeyExpression =
            x => string.Equals(x.LOG_CORR_KEY, model.CorrelationKey, StringComparison.CurrentCultureIgnoreCase);
        Expression<Func<Event, bool>> searchForLsidExpressionExpression =
            x => string.Equals(x.LOG_LSID, model.LsId, StringComparison.CurrentCultureIgnoreCase);
        Expression<Func<Event, bool>> searchForLogLocationExpression =
            x => string.Equals(x.LOG_LOCATION, model.LogLocation, StringComparison.CurrentCultureIgnoreCase);
        Expression<Func<Event, bool>> searchForLogTypeExpression =
            x => string.Equals(x.LOG_TP, model.LogType.ToString(), StringComparison.CurrentCultureIgnoreCase);
        if (model.EndDateTime != null && model.StartDateTime != null)
        {
            Expression<Func<Event, bool>> searchForLogInDateRangeExpression =
                x => model.StartDateTime <= x.LOG_TS && model.EndDateTime <= x.LOG_TS;
        }   
        Expression<Func<Event, bool>> searchForLogByUserIdExpression =
            x => string.Equals(x.LOG_USERID, model.UserId.ToString(), StringComparison.CurrentCultureIgnoreCase);

        Expression<Func<Event, bool>> searchForLogByLogTextExpression =
            x => string.Equals(x.LOG_TXT, model.SearchString.ToString(), StringComparison.CurrentCultureIgnoreCase);

我有 7 个表达式要合并为一个,然后将其放入接受 Expression&lt;Func&lt;Event, bool&gt;&gt; 作为参数的方法中。

有可能吗?我发现了很多组合两个表达式的示例,但它们不起作用。

【问题讨论】:

  • 你试过 var body = Expression.AndAlso(expr1.Body, expr2.Body);在循环中?
  • 你说的他们没有工作是什么意思。每个谓词构建器助手都可以工作 - Universal Predicate Buildermy own、著名的 PredicateBuilder 等。
  • @MistyK 据我所知,它可能只需要参数/表达式。我需要输入 7 个表达式。或者你的想法中遗漏了什么?
  • @IvanStoev 这些示例与所有其他示例一样基于两个表达式。我需要以某种方式将七个表达式合二为一。或者也许我不明白这些示例中的某些内容。
  • 他们可以被锁住 - expr1.And(expr2).And(expr3).And(expr4)...

标签: c# .net expression


【解决方案1】:

小提琴:https://dotnetfiddle.net/V7Ol0J

知识来源:https://www.codeproject.com/Articles/895951/Combining-expressions-to-dynamically-append-criter

这是一个工作示例:

   public class Event
    {
        public string A {get;set;}
        public string B {get;set;}
        public string C {get;set;}
    }




public static class Extensions
{
    public static Expression<Func<T, Boolean>> AndAlso<T>(this Expression<Func<T, Boolean>> left, Expression<Func<T, Boolean>> right)
        {
            Expression<Func<T, Boolean>> combined = Expression.Lambda<Func<T, Boolean>>(
                Expression.AndAlso(
                    left.Body,
                    new ExpressionParameterReplacer(right.Parameters, left.Parameters).Visit(right.Body)
                    ), left.Parameters);

                     return combined;
        }
    }



    public class ExpressionParameterReplacer : ExpressionVisitor
    {
        private IDictionary<ParameterExpression, ParameterExpression> ParameterReplacements { get; set; }

        public ExpressionParameterReplacer(IList<ParameterExpression> fromParameters, IList<ParameterExpression> toParameters)
        {
            ParameterReplacements = new Dictionary<ParameterExpression, ParameterExpression>();

            for(int i = 0; i != fromParameters.Count && i != toParameters.Count; i++)
            { ParameterReplacements.Add(fromParameters[i], toParameters[i]); }
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            ParameterExpression replacement;

            if(ParameterReplacements.TryGetValue(node, out replacement))
            { node = replacement; }

            return base.VisitParameter(node);
        }           
    }

用法:

            Expression<Func<Event, bool>> searchForLogCorrelationKeyExpression = x => string.Equals(x.A, "A", StringComparison.CurrentCultureIgnoreCase);
            Expression<Func<Event, bool>> searchForLsidExpressionExpression =  x => string.Equals(x.B, "B", StringComparison.CurrentCultureIgnoreCase);
            Expression<Func<Event, bool>> searchForLogLocationExpression = x => string.Equals(x.C, "C", StringComparison.CurrentCultureIgnoreCase);

            var res = searchForLogCorrelationKeyExpression.AndAlso(searchForLsidExpressionExpression).AndAlso(searchForLogLocationExpression);

            Console.WriteLine(res.Compile()(new Event(){A="A",B="B",C="C"}));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-13
    相关资源
    最近更新 更多