简体   繁体   English

linq表达式作为参数

[英]linq expression as parameter

I have to query collection like this: 我必须像这样查询集合:

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

s.CountryCode above is an example. s.CountryCode上面是一个例子。 I want to make it variable and call for different columns, like this: 我想让它变量并调用不同的列,如下所示:

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 function where the column expression is a parameter. 所以我想定义列表达式是参数的函数。 What is the signature of such function? 这种功能的签名是什么?

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

myList is an ObservableCollection , and myFilters is List<string> myList是一个ObservableCollectionmyFiltersList<string>

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)));
}

The way this extension method works is that it accepts a lambda function that resolves the property given an object of your type. 此扩展方法的工作方式是它接受一个lambda函数,该函数解析给定类型对象的属性。 So you just need to pass a simple lamba like x => x.City to it. 所以你只需要将一个像x => x.City这样的简单lamba x => x.City给它。

Since it's completely generic and not specific to your one myFilters collection, you also need to pass it to the function. 由于它是完全通用的,并不是特定于您的myFilters集合,因此您还需要将其传递给该函数。 But that allows you to use this WhereContains for many other situations too. 但是,这允许您在许多其他情况下使用此WhereContains

Using it 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

You can use Reflection 你可以使用Reflection

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

As an alternative solution you can use the following approach which allows to specify either filter field or 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 methods are implemented as follows: 这里的@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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM