我有一个Model对象列表和一个包含信息的xml,根据这些信息应该过滤列表。我需要一个过滤方法,它接受list和xml并返回过滤后的列表。我需要它是通用的,因此它可以处理一个列表,即ProductModel或CustomerModel列表。 xml可以包含<descriptor>
个元素或<composite>
个元素,如下所示。 FilterCompositionLogicalOperator
属性指示它是逻辑AND
还是逻辑OR
操作。 FilterOperator
表示eksample IsEqualTo = 0
IsLessThan=1
等的枚举。
<?xml version="1.0" encoding="utf-8" ?>
<advanced FilterCompositionLogicalOperator="1">
<descriptor IsCaseSensitive="false" Member="SalesPrice" MemberType="System.Decimal" FilterOperator="5">800</descriptor>
<descriptor IsCaseSensitive="false" Member="CostPrice" MemberType="System.Decimal" FilterOperator="5">300</descriptor>
<composite FilterCompositionLogicalOperator="0">
<descriptor IsCaseSensitive="false" Member="CostPrice" MemberType="System.Decimal" FilterOperator="5">150</descriptor>
<descriptor IsCaseSensitive="false" Member="ProductId" MemberType="System.String" FilterOperator="0">400</descriptor>
</composite>
</advanced>
我尝试过这样的事情:
public List<IAdvancedFilterable> HandleXML(XElement xml, IEnumerable<IAdvancedFilterable> filterableList)
{
foreach (XElement element in xml.Elements())
{
// if composite, I call the method recursively giving it the composite element and list
// else I read all the attributes of the <descriptor> element. decide the type of the elementValue
// and then I call helper method 'Filter'
filtered = Filter(compareOpr, colNameAtt.Value, elementValue, list);
// Which filters the list according to this <descriptor> element using LINQ.
}
return filtered;
}
如何处理OR情况。并且很简单 - 您只需根据每个<descriptor>
进行过滤,无需进一步考虑就可以了。
Filter helper方法打开FilterOperator
,例如:
case FilterOperator.IsLessThan:
if (elementValue.IsInt())
return list.Where(d => Convert.ToInt32(d.Source.GetColumnValue(columnName)) < Convert.ToInt32(elementValue));
if (elementValue.IsDecimal())
return list.Where(d => Convert.ToDecimal(d.Source.GetColumnValue(columnName)) < Convert.ToDecimal(elementValue));
break;
我的模型对象有一个方法GetColumnValue(columnName)
,它接受一个columnName并返回它的值。
知道如何有效地实现这一目标吗? LINQ Performant在这种情况下?是否有更好的替代方案以获得更好的性能?
答案 0 :(得分:0)
您可以采取以下方式:
使用方法bool Evaluate(XElement element)
实施2个课程:Filter
和CompositeFilter
。
一个。 CompositeFilter
应该有一个子过滤器列表和一个标志,指示它是AND还是OR条件。 Evaluate
方法实现应该根据AND / OR标志评估所有子过滤器并返回结果的逻辑组成
class CompositeFilter {
bool IsANDCondition; // if false, it is OR;
List<IFilter> childFilters;
bool Evaluate(XElement element) {
bool result = IsANDCondition;
foreach (var filter in childFilters)
{
bool b = filter.Evaluate(element);
if (IsANDCondition)
result = b && result;
else
result = b || result;
}
return result;
}
}
湾Filter
应具有所有可能的属性(IsCaseSensitive,Member,MemberType等)并在Evaluate方法中实现逻辑
通过这种方式,您将拥有一个递归计算的谓词,您可以轻松地将其应用于您的记录:
CompositeFilter filter;
var fiteredRecords = records.Where(x=>filter.Evaluate(x));