【问题标题】:Identify number of conditions in a dynamic LINQ expression识别动态 LINQ 表达式中的条件数
【发布时间】:2019-08-03 09:50:22
【问题描述】:

我选择在我的项目中实现System.Linq.Dynamic 命名空间,我依赖于从字符串动态调用LINQ 表达式来针对我的底层对象。这允许在数据级别进行高度可配置的标准。

string expression = "x.Client == 100 && x.Insurers.Any(it == 2 || it == 3)";
var x = new MyObject() { Client = 100, Insurers = new int[] { 1, 2 }};   
var p = Expression.Parameter(typeof(MyObject), "x");
var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, expression);
bool result = e.Compile().DynamicInvoke(x); // True = condition met

我的问题是如何动态识别每个字符串表达式包含的条件数量,以便我可以为每个表达式赋予权重,并在发生重叠时选择权重最高的一个。 Regex可以工作,但必须有更高效和实用的东西,比如表达式树。

例如:

x.Client == 100 // Conditions = 1
x.Client == 100 && x.Insurers.Any(it == 3) // Conditions = 2
x.Client == 100 && x.Insurers.Any(it == 2 || it == 3) // Conditions = 3

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    我不熟悉System.Linq.Dynamic 库,但假设它生成正常的强类型Expression 树,您可以使用ExpressionVisitor

    这个计算布尔逻辑运算的数量,如&&

    int CountConditions(Expression expr)
    {
        var visitor = new CountBinaryOpsVisitor();
        visitor.Visit(expr);
        return visitor.BinaryOperationCount + 1;
    }
    
    class CountBinaryOpsVisitor : ExpressionVisitor
    {
        public int BinaryOperationCount { get; private set; }
    
        protected override Expression VisitBinary(BinaryExpression node)
        {
            switch (node.NodeType)
            {
                case ExpressionType.And:
                case ExpressionType.AndAlso:
                case ExpressionType.Or:
                case ExpressionType.OrElse:
                case ExpressionType.ExclusiveOr:
                    // Don't count bitwise integer operations, if they are even supported?
                    if (node.Left.Type == typeof(bool))
                        BinaryOperationCount++;
                    break;
            }
            return base.VisitBinary(node);
        }
    }
    

    另一种方法是计算比较运算符的数量(==>= 等),但我认为这需要更复杂的代码来处理布尔表达式,如 x.BooleanPropx.Insurers.Any()

    此实现目前不计算条件表达式 (x ? y : z)。不确定如何将这些因素计入条件数量,尤其是嵌套时。

    【讨论】:

    • 计数比较运算符应该和计数逻辑运算符一样容易,只是一组不同的ExpressionTypes。
    • @NetMage 我所指的复杂之处在于,像x => x.BooleanProperty 这样的布尔表达式不会生成任何特定的比较或真实性表达式,它只是一个MemberAccessCall 等. 因此,您需要将布尔值与 x.Foo.Bar.IntegerProperty 等其他成员访问区分开来,然后确保您不会两次计算 x.BooleanExpression == true
    • @kalimag 这样的回答让我意识到我还需要了解多少 C#。谢谢!
    猜你喜欢
    • 2013-12-30
    • 2010-09-07
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多