C# 动态构建嵌套谓词
我正在尝试从xml字符串动态构建谓词,例如,xml字符串的格式如下所示: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>
<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();