1

嗨,我必须在泛型类上应用过滤器。示例类如下

public class Sample<T>
{
    List<T> sourceList = new List<T>();

    public void applyFilter(string propertyName , EnumOperator operator , object value)
    {

    }
}

在这里,我想使用 linq 或动态 linq 实现过滤器,但没有得到任何积极的方向来实现此功能。

请给我一些积极的方向,以便我可以实现此功能。

谢谢。

4

4 回答 4

3

我建议返回过滤列表而不是修改源,并且字符串“operator”是 C# 关键字,因此该方法的签名可以是:

public List<T> ApplyFilter(string propertyName, EnumOperator operatorType, object value)
{
   ....
}

我假设这EnumOperator是一个enum像这样的值:

public enum EnumOperator
{
   Equal,
   NotEqual,
   Bigger,
   Smaller
}

并且您有某种方法可以检查运算符的值是否通过或未通过测试,类似于:

public static class OperatorEvaluator
{ 
  public static bool Evaluate(EnumOperator operatorType, object first, object second)
  {
    ...
  }
}

鉴于此,您可以执行以下操作:

public List<T> ApplyFilter(string propertyName , EnumOperator operatorType, object value)
{
  PropertyInfo pi = typeof(T).GetProperty(propertyName);
  List<T> result = sourceList.Where(item => { 
    var propValue = pi.GetValue(item, null);
    return OperatorEvaluator.Evaluate(operatorType, propValue, value);
  }).ToList();
  return result;
}

也就是说,您始终可以使用 LINQ 的方法过滤几乎所有内容,而无需借助反射。

于 2012-12-28T09:59:06.373 回答
2

要使用动态表达式(作为字符串)进行查询,您可以使用Microsoft的Scott Gu的Dynamic LINQ 。

样品

它支持以下操作
1. Select
2. Where
3. OrderBy
4. Skip
5. Take
6. GroupBy

以上所有操作都以字符串为参数。

它还具有非常易于使用的小型表达式语言(用于构建选择器/谓词/等)。

例子:

var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");  
于 2012-12-28T10:18:30.070 回答
1

在这里,我给您一个示例示例,如何在List<T>项目上使用 LINQ 实现过滤。

public class clsCountry
{
    public string _CountryCode;
    public string _CountryName;
    //
    public clsCountry(string strCode, string strName)
    {
        this._CountryCode = strCode;
        this._CountryName = strName;
    }
    //
    public string CountryCode
    {
        get {return _CountryCode;}
        set {_CountryCode = value;}
    }
    //
    public string CountryName
    {
        get { return _CountryName; }
        set { _CountryName = value; }
    }
}

现在,让我们根据类创建一个对象列表clsCountry并将它们存储在一个List<T>对象中。

List<clsCountry> lstCountry = new List<clsCountry>();
lstCountry.Add(new clsCountry("USA", "United States"));
lstCountry.Add(new clsCountry("UK", "United Kingdom"));
lstCountry.Add(new clsCountry("IND", "India"));

接下来,我们将List<T>对象 lstCountry 绑定到DropDownList名为 drpCountry 的控件,如下所示:

drpCountry.DataSource = lstCountry;
drpCountry.DataValueField = "CountryCode";
drpCountry.DataTextField = "CountryName";
drpCountry.DataBind();

现在,使用 LINQ 过滤来自 lstCountry 对象的数据,并将过滤后的列表绑定到下拉控件 drpCountry。

 var filteredCountries = from c in lstCountry
                        where c.CountryName.StartsWith("U")
                        select c;

drpCountry.DataSource = filteredCountries;
drpCountry.DataValueField = "CountryCode";
drpCountry.DataTextField = "CountryName";
drpCountry.DataBind();

现在下拉控件将​​只有 2 个项目

美国
英国

现在将这些技术应用于您的案例..

于 2012-12-28T10:10:23.493 回答
0

您可以使用 Reflection 来检索属性值,并且可以使用switch操作符上的简单语句来执行过滤:

public IEnumerable<T> ApplyFilter(string propertyName, EnumOperator op, object value)
{
    foreach (T item in sourceList)
    {
        object propertyValue = GetPropertyValue(item, propertyName);
        if (ApplyOperator(item, propertyValue, op, value)
        {
            yield return item;
        }
    }
}

private object GetPropertyValue(object item, string propertyName)
{
    PropertyInfo property = item.GetType().GetProperty(propertyName);
    //TODO handle null
    return property.GetValue();
}

private bool ApplyOperator(object propertyValue, EnumOperator op, object value)
{
    switch (op)
    {
        case EnumOperator.Equals:
            return propertyValue.Equals(value);
        //TODO other operators
        default:
            throw new UnsupportedEnumException(op);
    }
}

PropertyInfo(优化是在循环外查找一次。)

于 2012-12-28T10:01:27.220 回答