过滤模板列表,属性名称为字符串

时间:2012-12-28 09:34:06

标签: c# .net linq generics linq-to-objects

您好我必须在泛型类上应用过滤器。样本类如下

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

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

    }
}

这里我想使用linq或dynamic linq实现过滤器,但是没有任何积极的方向来实现这个功能。

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

感谢。

4 个答案:

答案 0 :(得分:3)

我建议返回一个已过滤的列表,而不是修改源,以及字符串&#34;运算符&#34;是一个C#关键字,因此方法的签名可以是:

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

我假设EnumOperatorenum,其值如下:

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的方法来过滤几乎任何东西而不需要反思。

答案 1 :(得分:2)

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

Samples

支持以下操作
1.选择
2.凡凡 3.订单由 4.跳过
5.取 6. GroupBy

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

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

示例:

var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");  

答案 2 :(得分: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绑定到名为drpCountry的DropDownList控件,如下所示:

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个项目

美国
英国

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

答案 3 :(得分: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。)