2

我有一个模型对象列表和一个 xml,其中包含应根据该列表过滤的信息。我需要一个过滤器方法,它接受列表和 xml 并返回过滤后的列表。我需要它是通用的,以便它可以处理即ProductModel 列表或CustomerModel 列表。xml 可以具有如下所示的<descriptor>元素或元素。<composite>FilterCompositionLogicalOperator属性指示它是逻辑操作AND还是逻辑OR操作。FilterOperator表示 eksampleIsEqualTo = 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 情况。AND 很容易 - 您只需根据每个过滤器进行过滤,<descriptor>无需任何进一步考虑就可以了。

Filter 辅助方法打开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 是高性能的吗?是否有更好的选择以获得更好的性能?

4

1 回答 1

0

您可以按照以下方式进行:

  1. 使用方法创建接口 IFilter:bool Evaluate(XElement element)

  2. 实现 2 个类:FilterCompositeFilter.

    一个。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));
于 2012-11-12T06:17:54.653 回答