我必须像这样查询集合:
myList.Where(s => myFilters.Contains(s.CountryCode))
上面的 s.CountryCode
就是一个例子。我想让它变量并调用不同的列,如下所示:
myList.Where(s => myFilters.Contains(s.City))
myList.Where(s => myFilters.Contains(s.Region))
myList.Where(s => myFilters.Contains(s.Zipcode))
所以我想定义列表达式是参数的函数。这种功能的签名是什么?
public void MySelect( ??? )
{
myList.Where(s => myFilters.Contains(???);
}
myList
是ObservableCollection
,myFilters
是List<string>
答案 0 :(得分:10)
将此扩展方法放在静态类中:
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)));
}
此扩展方法的工作方式是它接受一个lambda函数,该函数解析给定类型对象的属性。所以你只需要将一个像x => x.City
之类的简单lamba传递给它。
由于它完全是通用的而不是特定于您的myFilters
集合,因此您还需要将其传递给该函数。但是,这也允许您在许多其他情况下使用此WhereContains
。
使用它看起来像这样:
// 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
答案 1 :(得分:1)
您可以使用反射
public void MySelect(string column)
{
var result = myList.Where(s => myFilters.Contains(s.GetType().GetProperty(column)));
}
答案 2 :(得分:0)
作为替代解决方案,您可以使用以下方法,该方法允许指定过滤器字段或过滤器功能:
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}
此处@Specify
扩展方法实现如下:
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
}
}