C# 如何(同时)在列表上应用多个筛选条件?

C# 如何(同时)在列表上应用多个筛选条件?,c#,linq,generics,design-patterns,specification-pattern,C#,Linq,Generics,Design Patterns,Specification Pattern,我使用.NET4.0框架编写了以下C代码。这是在引用后创建的 在GetProducts()中,要使用的条件在方法内部定义(硬编码)。还有另一个方法名为getProductsBasedInputFilters()。在该方法中,规范列表作为该方法的参数 问题 在这种方法中,在产品列表上应用这些过滤器的最佳方法是什么 注意:我尝试在foreach循环中应用FindAll子句,并将结果添加到列表中。但这种逻辑是不正确的——只有那些满足所有条件的项目才需要返回 注意:ProductSpecificatio

我使用
.NET4.0
框架编写了以下C代码。这是在引用后创建的

GetProducts()
中,要使用的条件在方法内部定义(硬编码)。还有另一个方法名为
getProductsBasedInputFilters()
。在该方法中,规范列表作为该方法的参数

问题

在这种方法中,在产品列表上应用这些过滤器的最佳方法是什么

注意:我尝试在
foreach
循环中应用
FindAll
子句,并将结果添加到
列表中。但这种逻辑是不正确的——只有那些满足所有条件的项目才需要返回

注意:ProductSpecifications列表中的规格数量将根据用户输入而变化

注意:在“”中提到的方法似乎很有用。然而,我不知道如何在这里使用这种方法,因为我处理的是
规范列表
;非
一般委托

过滤方法

public static class ProductFilterHelper
{
    public static List<Product> GetProducts(List<Product> list)
    {
        double priceLimit = 100;

        //FIRST::
        //List<Product> selectedList =  list.FindAll(new OnSaleSpecification().IsSatisfiedBy);

        //SECOND::
        //AndSpecification<Product> spec = new AndSpecification<Product>(new OnSaleSpecificationForProduct(), new PriceGreaterThanSpecificationForProduct(priceLimit));
        //List<Product> selectedList = list.FindAll(spec.IsSatisfiedBy); 


        //THIRD:
        List<Product> selectedList = list.FindAll(new OnSaleSpecificationForProduct()
                                                       .And(new PriceGreaterThanSpecificationForProduct(priceLimit))
                                                       .And(new PriceGreaterThan105())
                                                       .IsSatisfiedBy
                                                  );

        return selectedList;
    }

    public static List<Product> GetProductsBasedOnInputFilters(List<Product> productList, List<Specification<Product>> productSpeifications)
    {
        List<Product> selectedList = new List<Product>();

        foreach (Specification<Product> specification in productSpeifications)
        {
            List<Product> currentList = productList.FindAll(specification.IsSatisfiedBy);

            if (currentList != null && currentList.Count > 0)
            {
                foreach (Product p in currentList)
                {
                    if (!selectedList.Contains(p))
                    {
                        selectedList.Add(p);
                    }
                }
            }
        }

        return selectedList;
    }        

}
public abstract class Specification<T>
{
    public abstract bool IsSatisfiedBy(T obj);

    public AndSpecification<T> And(Specification<T> specification)
    {
        return new AndSpecification<T>(this, specification);
    }

    public OrSpecification<T> Or(Specification<T> specification)
    {
        return new OrSpecification<T>(this, specification);
    }

    public NotSpecification<T> Not(Specification<T> specification)
    {
        return new NotSpecification<T>(this, specification);
    }
}

public abstract class CompositeSpecification<T> : Specification<T>
{
    protected readonly Specification<T> _leftSide;
    protected readonly Specification<T> _rightSide;

    public CompositeSpecification(Specification<T> leftSide, Specification<T> rightSide)
    {
        _leftSide = leftSide;
        _rightSide = rightSide;
    }
}
public class AndSpecification<T> : CompositeSpecification<T>
{
    public AndSpecification(Specification<T> leftSide, Specification<T> rightSide)
        : base(leftSide, rightSide)
    {

    }

    public override bool IsSatisfiedBy(T obj)
    {
        return _leftSide.IsSatisfiedBy(obj) && _rightSide.IsSatisfiedBy(obj);
    }
}

public class OrSpecification<T> : CompositeSpecification<T>
{
    public OrSpecification(Specification<T> leftSide, Specification<T> rightSide)
        : base(leftSide, rightSide)
    {
    }

    public override bool IsSatisfiedBy(T obj)
    {
        return _leftSide.IsSatisfiedBy(obj) || _rightSide.IsSatisfiedBy(obj);
    }
}

public class NotSpecification<T> : CompositeSpecification<T>
{
    public NotSpecification(Specification<T> leftSide, Specification<T> rightSide)
        : base(leftSide, rightSide)
    {
    }

    public override bool IsSatisfiedBy(T obj)
    {
        return _leftSide.IsSatisfiedBy(obj) && !_rightSide.IsSatisfiedBy(obj);
    }
}
public class OnSaleSpecificationForProduct : Specification<Product>
{
    public override bool IsSatisfiedBy(Product product)
    {
        return product.IsOnSale;
    }
}

public class PriceGreaterThanSpecificationForProduct : Specification<Product>
{
    private readonly double _price;
    public PriceGreaterThanSpecificationForProduct(double price)
    {
        _price = price;
    }

    public override bool IsSatisfiedBy(Product product)
    {
        return product.Price > _price;
    }
}

public class PriceGreaterThan105 : Specification<Product>
{

    public override bool IsSatisfiedBy(Product product)
    {
        return product.Price > 105;
    }
}
参考资料


  • 下面的代码工作。。。欢迎提出建议

     public static List<Product> GetProductsBasedOnInputFilters(List<Product> productList, List<Specification<Product>> productSpecifications)
     {
                IEnumerable<Product> selectedList = productList;
                foreach (Specification<Product> specification in productSpecifications)
                {
                    selectedList = selectedList.Where(specification.IsSatisfiedBy);
                }
                return selectedList.ToList();
     }
    
    公共静态列表GetProductsBasedInputFilters(列表productList,列表productSpecifications)
    {
    IEnumerable selectedList=产品列表;
    foreach(产品规范中的规范)
    {
    selectedList=selectedList.Where(specification.Issatifiedby);
    }
    返回selectedList.ToList();
    }
    
    下面的内容也值得一看


  • 您可以执行以下几项操作之一:

    • 通过将
      Where
      调用堆叠在彼此的顶部来组合过滤器,如@Lijo的答案中所示

    • 检查每个项目的所有规格:

      return productList
        .Where(p => specifications.All(ps => ps.IsSatisfiedBy(p))
        .ToList()
      
    • 创建一个复合“And”规范,该规范接受多个子规范,而不是两个子规范:

      public class AndSpecification<T> : ISpecification<T>
      {
          private ISpecification<T>[] _components;
      
          public AndSpecification(ISpecification<T>[] components) 
          {
            _components = components;
          }
      
          public bool IsSatisfiedBy(T item) 
          {
            return components.All(c => c.IsSatisfiedBy(item));
          }
        }
      

      清单上的项目必须符合所有或其中任何一项规范吗?还有,为什么不在ConradFrix做点什么呢?它应该满足所有的规范。中提到的方法似乎很有用。然而,我不知道如何在这里使用它,因为我正在处理
      规范列表
      ;非
      一般代表
      。更新:相关问题:谢谢。。我打算用
      All
      。。我当前的代码是
      returnproductlist.Where(p=>productSpecifications.All(ps=>ps.issatifiedby(p)).ToList()
      
      return productList
        .Where(p => specifications.All(ps => ps.IsSatisfiedBy(p))
        .ToList()
      
      public class AndSpecification<T> : ISpecification<T>
      {
          private ISpecification<T>[] _components;
      
          public AndSpecification(ISpecification<T>[] components) 
          {
            _components = components;
          }
      
          public bool IsSatisfiedBy(T item) 
          {
            return components.All(c => c.IsSatisfiedBy(item));
          }
        }
      
      var allFiltersSpecification = new AndSpecification(specifications)
      return productList.Where(allFiltersSpecification.IsSatisfiedBy);