C# 动态构建嵌套谓词

C# 动态构建嵌套谓词,c#,.net,xml,linq,predicatebuilder,C#,.net,Xml,Linq,Predicatebuilder,我正在尝试从xml字符串动态构建谓词,例如,xml字符串的格式如下所示: <Group Operation="AND"> <Group Operation="AND"> <Group Operation="OR"> <Filter> (ContainsValue) </Filter> <Filter> (StartsWithValue) </Filter>

我正在尝试从xml字符串动态构建谓词,例如,xml字符串的格式如下所示:

<Group Operation="AND">
    <Group Operation="AND">
      <Group Operation="OR">
        <Filter> (ContainsValue) </Filter>
        <Filter> (StartsWithValue) </Filter>
      </Group>
      <Filter> (HasData) </Filter>
    </Group>
    <Filter> (SomeotherCondition) </Filter>
</Group>
我想问的是:

  • 我是否试图通过嵌套谓词实现一些不可信的东西
  • 如果这是合理的,我做错了什么?我读了那本书 根据嵌套谓词部分,我看不出我的谓词在哪里 错

这是我第一次使用这样的谓词,我可能做了一些非常明显的非常错误的事情,如果是这样的话,那么很抱歉,但是如果你对我如何实现我正在尝试的目标有任何想法,我将感谢你的帮助。谢谢。

对不起,我不知道该怎么办@Samiam最后构建的谓词在分组方面看起来不错,但是它很长,不容易阅读,所以我没有复制它。这是一篇关于如何使用调试程序的文章。很明显。对不起,我不确定我应该对此做些什么@Samiam最后构建的谓词在分组方面看起来不错,但是它很长,不容易阅读,所以我没有复制它。这是一篇关于如何使用Debugger的文章。
    public Stack<FilterExpressionModel> RecursiveExpressionBuilder(XElement root, Stack<FilterExpressionModel> stackelement)
    {
        Stack<Expression<Func<Product, bool>>> stackexpression = new Stack<Expression<Func<Product, bool>>>();
        var left = root.Elements().FirstOrDefault();
        var right = root.Elements().Count() == 1 ? null : root.Elements().LastOrDefault();
        if (left != null)
        {
            stackelement = RecursiveExpressionBuilder(left, stackelement);
        }
        if (right != null)
        {
            stackelement = RecursiveExpressionBuilder(right, stackelement);
        }
        if (root.Name == FilterQueryNodes.Filter)
        {
            stackelement.Push(new FilterExpressionModel() { FilterNode = root });
        }
        else if (root.Name == FilterQueryNodes.Group)
        {
            var operand2Candidate = stackelement.Pop();
            var operand1Candidate = stackelement.Pop();
            //following grabs the actual expression for the corresponding value of the xml node for example (d=>d.Value.Contains(filterValue)) for Contains
            //if the node is "filter" it grabs the filter if not, it grabs the predicate that has been built so far
            var operand1 = operand1Candidate.FilterNode != null ? FilterExpression(GetFilterRule(Convert.ToInt32(operand1Candidate.FilterNode.Value))) : operand1Candidate.PredicateBuilding;
            var operand2 = operand2Candidate.FilterNode != null ? FilterExpression(GetFilterRule(Convert.ToInt32(operand2Candidate.FilterNode.Value))) : operand2Candidate.PredicateBuilding;
            string operation = root.Attribute(FilterQueryNodes.Operation).Value;

            var predicate = BuildPredicate(operand1, operand2, operation);
            stackelement.Push(new FilterExpressionModel() { PredicateBuilding = predicate });
        }
        return stackelement;
    }

    public Expression<Func<Product, bool>> BuildPredicate(Expression<Func<Product, bool>> operand1, Expression<Func<Product, bool>> operand2, string operation)
    {
        switch (operation)
        {
            case "AND":
                operand1 = operand1.And(operand2);
                return operand1;
            case "OR":
                operand1 = operand1.Or(operand2);
                return operand1;
            default:
                return (d => true);
        }
    }
//this class is to hold the grouped predicate and the filter so that I will only have one stack
    public class FilterExpressionModel
    {
        public FilterExpressionModel() {

        }
        public Expression<Func<FieldValues, bool>> PredicateBuilding { get; set; }
        public XElement FilterNode { get; set; } 
    }
<Root>
    <Group Operation="AND">
      <Filter>23</Filter>
      <Filter>22</Filter>
    </Group>
</Root>
products.Where(builtpredicate).ToList();