Linq expression as parameter

I need to request the assembly as follows:

myList.Where(s => myFilters.Contains(s.CountryCode)) 

s.CountryCode is an example. I want to make it a variable and call different columns, for example:

 myList.Where(s => myFilters.Contains(s.City)) myList.Where(s => myFilters.Contains(s.Region)) myList.Where(s => myFilters.Contains(s.Zipcode)) 

So, I would like to define a function where the column expression is a parameter. What is the signature of such a function?

 public void MySelect( ??? ) { myList.Where(s => myFilters.Contains(???); } 

myList is an ObservableCollection , and myFilters is a List<string>

+6
source share
3 answers

Put this extension method in a static class:

 public static IEnumerable<T> WhereContains<T, TValue> (this IEnumerable<T> obj, IEnumerable<TValue> container, Func<T, TValue> propertyAccess) { return obj.Where(o => container.Contains(propertyAccess(o))); } 

How this extension method works, it takes a lambda function that resolves the property specified by an object of your type. So you just need to pass a simple lamba, for example x => x.City .

Since it is completely general and not specific to your myFilters collection, you also need to pass it functions. But this allows you to use this WhereContains for many other situations.

Usage looks like this:

 // Test is a class with two string properties `City` and `Region` var myList = new List<Test>{ new Test() { City = "asdf", Region = "fdsa" }, new Test() { City = "foo", Region = "bar" }, new Test() { City = "bar", Region = "baz" } }; var myFilters = new List<string> { "asdf", "bar" }; myList.WhereContains(myFilters, x => x.City); // contains asdf/fdsa and bar/baz myList.WhereContains(myFilters, x => x.Region); // contains foo/bar 
+10
source

You can use reflection

  public void MySelect(string column) { var result = myList.Where(s => myFilters.Contains(s.GetType().GetProperty(column))); } 
+1
source

As an alternative solution, you can use the following approach, which allows you to specify either a filter field or a filter function:

 var adresses = new List<Address>{ new Address() { City = "ABC", Country = "USA" }, new Address() { City = "BC", Country = "USA" }, new Address() { City = "C", Country = "UK" } }; var filterValues = new List<string> { "B", "UK", "U" }; // var FilterContains = filterValues.@Specify ((values, value) => values.Contains(value)); var FilterStartsWith = filterValues.@Specify ((values, value) => values.Any(v => value.StartsWith(v))); // var AdressesByCity = adresses.@Specify (a => a.City); var adressesByCitiesContains = AdressesByCity(filterValues, FilterContains); // B->{ABC;USA},{BC;USA} var adressesByCitiesStartsWith = AdressesByCity(filterValues, FilterStartsWith);// B->{BC;USA} // var AdressesByCountry = adresses.@Specify (a => a.Country); var adressesByCountriesContains = AdressesByCountry(filterValues, FilterContains);//U,UK-> {C;UK} var adressesByCountriesStartsWith = AdressesByCountry(filterValues, FilterStartsWith); //U,UK->{ABC;USA},{BC;USA}{C;UK} 

Here the @Specify extension @Specify implemented as follows:

 public static class @SpecifyExtension { public static Func<IEnumerable<V>, Func<IEnumerable<V>, V, bool>, IEnumerable<U>> @Specify<U, V>(this IEnumerable<U> source, Func<U, V> selector) { return (values, predicate) => source.Where(x => predicate(values, selector(x))); } public static Func<IEnumerable<TValue>, TValue, bool> @Specify<TValue>(this IEnumerable<TValue> source, Func<IEnumerable<TValue>, TValue, bool> func) { return func; // for Type-inference only } } 
0
source

All Articles