将过滤器应用于Where

时间:2016-07-21 18:49:04

标签: c# entity-framework

我创建了以下RangeFilter:

public class RangeFilter<T> : IFilter<T> where T : struct, IConvertible, IComparable {

  public T? Maximum { get; private set; }
  public T? Minimum { get; private set; }

  public RangeFilter(T? minimum, T? maximum) {
    Minimum = minimum;
    Maximum = maximum;
  }

  public Boolean Matches(T value) {

    if (Minimum != null && Maximum != null)
      return value.CompareTo(Minimum) >= 0 && value.CompareTo(Maximum) <= 0;
    if (Minimum == null && Maximum != null)
      return value.CompareTo(Maximum) <= 0;

    if (Minimum != null && Maximum == null)
      return value.CompareTo(Minimum) >= 0;

    return false;

  } // Matches

} // RangeFilter

可以使用如下:

RangeFilter<Int32> filter = new RangeFilter<Int32>(2, 4);

Boolean match = filter.Matches(2);

我需要将其整合为Where扩展名:

public class Product {
  public Int32 Rating { get; set; }
}

List<Product> products = context.Products.Where(x => x.Rating, filter);

所以我将Filter应用于x.Rating的值......

我这样做是因为我将有多个Filter类型都实现IFilter和更多东西。

如何创建此扩展程序?

1 个答案:

答案 0 :(得分:1)

public static class FilterExtensions
{
    public static bool Matches<T>(this T input, IFilter<T> filter) 
        where T : struct, IConvertible, IComparable
    {
        return filter.Matches(input);
    }
}

List<Product> products = context.Products.Where(x => x.Rating.Matches(filter));

相同
List<Product> products = context.Products.Where(x => filter.Matches(x.Rating));

在评论中添加了以下内容:

  

因为我将在Where里面有多种类型的过滤器   扩展我将根据a确定哪种类型的过滤器   表达我也会通过。

我不确定是否需要添加扩展名,因为在这种情况下,扩展名似乎是多余的。

如果您的Linq查询中有一个表达式确定要使用哪个过滤器,则该查询可能难以阅读。如果您确定需要根据多个属性进行过滤,则可能会非常混乱。

基于此,我建议为整个类定义过滤器,而不仅仅是一个属性。您可以IFilter<T> T Product,而不是Product的属性。

这使您可以将ProductFilter编写为可以进行单元测试的类。当你有一个条件,这个类非常简单。如果您有更多条件,则可以修改ProductFilter并注入Func<Product, bool>的集合,并在条件下运行每个Product

我不建议在前面进行全面的过度杀伤。但是如果你像那些过滤器一样采用逻辑并将它们分成不同的类,那么你就完成了一些事情:

  • 您可以对这些过滤器进行单元测试
  • 如果方法需要过滤器,您可以对其进行模拟,以便您可以测试除过滤器之外的方法
  • 阅读会更容易。