Filtering on template list with property name as string

前端 未结 4 1504
灰色年华
灰色年华 2021-01-16 06:26

Hi I have to apply filter on generic class. The sample class is as follows

public class Sample
{
    List sourceList = new List();         


        
相关标签:
4条回答
  • 2021-01-16 06:43

    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.

    0 讨论(0)
  • 2021-01-16 06:50

    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.)

    0 讨论(0)
  • 2021-01-16 06:56

    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)");  
    
    0 讨论(0)
  • 2021-01-16 07:00

    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..

    0 讨论(0)
提交回复
热议问题