过滤模板列表与属性名作为字符串(Filtering on template list with pr

2019-07-17 15:19发布

您好我必须在泛型类应用滤镜。 示例类是如下

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

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

    }
}

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

请给我一些积极的方向,这样我可以实现这个功能。

谢谢。

Answer 1:

我会建议返回一个过滤列表,而不是修改源,也是字符串“经营者”是一个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的方法,而不是诉诸反射来过滤几乎所有的东西。



Answer 2:

要使用动态表情(如字符串)查询,您可以使用动态LINQ由斯科特谷微软的。

样品

它支持以下操作
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)");  


Answer 3:

在这里,我给你一个样品例如如何使用LINQ来实现过滤List<T>的项目..

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项

美国
英国
现在适用于你的情况下,这些技术..



Answer 4:

您可以使用反射检索属性值,你可以使用一个简单的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一次循环外)。



文章来源: Filtering on template list with property name as string