过滤模板列表,属性名称为字符串
嗨,我必须在generics类上应用filter。 样本类如下
public class Sample { List sourceList = new List(); public void applyFilter(string propertyName , EnumOperator operator , object value) { } }
在这里,我想使用linq或动态linq实现filter,但是没有得到任何积极的方向来实现这个function。
请给我一些积极的方向,以便我可以实现此function。
谢谢。
我建议返回一个过滤列表而不是修改源,并且字符串“operator”是一个C#关键字,因此方法的签名可以是:
public List 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 ApplyFilter(string propertyName , EnumOperator operatorType, object value) { PropertyInfo pi = typeof(T).GetProperty(propertyName); List result = sourceList.Where(item => { var propValue = pi.GetValue(item, null); return OperatorEvaluator.Evaluate(operatorType, propValue, value); }).ToList(); return result; }
也就是说,你总是可以使用LINQ的方法来过滤几乎任何东西,而无需借助reflection。
要使用动态表达式(作为字符串)进行查询,可以使用Microsoft的Scott Gu的Dynamic 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)");
这里我给你一个示例如何使用List
项上的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
对象中。
List lstCountry = new List (); lstCountry.Add(new clsCountry("USA", "United States")); lstCountry.Add(new clsCountry("UK", "United Kingdom")); lstCountry.Add(new clsCountry("IND", "India"));
接下来,我们将List
对象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个项目
美国
英国
现在将这些技术应用于您的案例..
您可以使用Reflection来检索属性值,并且可以在运算符上使用简单的switch
语句来执行过滤:
public IEnumerable 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
。)