问题
Hi I have to apply filter on generic class. The sample class is as follows
public class Sample<T>
{
List<T> sourceList = new List<T>();
public void applyFilter(string propertyName , EnumOperator operator , object value)
{
}
}
Here I want to implement filter using linq or dynamic linq but am not getting any positive direction to implement this functionality.
Please give me some positive direction so that I can implement this functionality.
Thanks.
回答1:
I would recommend returning an filtered list instead of modifying the source, and also the string "operator" is a C# keyword, so the signature of the method could be:
public List<T> ApplyFilter(string propertyName, EnumOperator operatorType, object value)
{
....
}
where I assume that the EnumOperator is an enum with values like this:
public enum EnumOperator
{
Equal,
NotEqual,
Bigger,
Smaller
}
and that you have some way to check if for an operator a value passes or fails the test, something along the lines of:
public static class OperatorEvaluator
{
public static bool Evaluate(EnumOperator operatorType, object first, object second)
{
...
}
}
Given that, you can do something like:
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;
}
That said, you can always use LINQ's methods to filter almost anything without resorting to reflection.
回答2:
To query with dynamic expression (as string), you can use Dynamic LINQ by Scott Gu of Microsoft.
Samples
It supports following operations
1. Select
2. Where
3. OrderBy
4. Skip
5. Take
6. GroupBy
All above operations take string as parameter.
It also has small expression language (to build selectors/predicates/etc) which is very easy to use.
Example:
var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");
回答3:
Here I give you a sample example how to implement filtering using LINQ on List<T> items..
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; }
}
}
Now, lets create a list of objects based on class clsCountry and store them in a List<T> object.
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"));
Next, we shall bind the List<T> object lstCountry to a DropDownList control named drpCountry as like as:
drpCountry.DataSource = lstCountry;
drpCountry.DataValueField = "CountryCode";
drpCountry.DataTextField = "CountryName";
drpCountry.DataBind();
Now, use LINQ to filter data from the lstCountry object and bind the filtered list to the dropdown control 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();
Now the dropdown control will have only 2 items
United States
United Kingdom
Now apply those techniques on your case..
回答4:
You can use Reflection for retrieving the property value and you can use a simple switch statement upon the operator to perform the filtering:
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);
}
}
(An optimization would be to look up the PropertyInfo once outside of the loop.)
来源:https://stackoverflow.com/questions/14067399/filtering-on-template-list-with-property-name-as-string