w2olves w2olves - 8 days ago 5
C# Question

Generic method to filter a list object

I am trying to create a generic method that takes three parameters.
1) List collection
2) String PropertyName
3) String FilterString

The idea is we pass a collection of Objects, the name of the property of the object
and a Filter Criteria and it returns back a list of Objects where the property contains
the FilterString.

Also, the PropertyName is optional so if its not supplied I would like to return
all objects that contain the FilterString in any property.

Any pointers on this would be really helpful.

I am trying to have a method signature like this:
public static List FilterList(List collection, String FilterString, String Property = "")

This way I can call this method from anywhere and pass it any List and it would return me a filtered list.

Answer

You could do what you want using LINQ, as such,

var collection = ...
var filteredCollection = 
    collection.Where(item => item.Property == "something").ToList();

Otherwise, you could try Reflection,

public List<T> Filter<T>(
    List<T> collection, 
    string property, 
    string filterValue)
{
    var filteredCollection = new List<T>();
    foreach (var item in collection)
    {
         // To check multiple properties use,
         // item.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)

         var propertyInfo = 
             item.GetType()
                 .GetProperty(property, BindingFlags.Public | BindingFlags.Instance);
         if (propertyInfo == null)
             throw new NotSupportedException("property given does not exists");             

         var propertyValue = propertyInfo.GetValue(item, null);
         if (propertyValue == filterValue)
             filteredCollection.Add(item);       
    }

    return filteredCollection;
}

The problem with this solution is that changes to the name of the property or misspellings result in a runtime error, rather than a compilation error as would be using an actual property expression where the name is hard-typed.

Also, do note that based on the binding flags, this will work only on public, non-static properties. You can modify such behavior by passing different flags.

Comments