假设我们有一个Person对象的集合
class Person
{
public string PersonName {get;set;}
public string PersonAddress {get;set;}
}
在代码定义的集合中的某个位置
List<Person> pesonsList = new List<Person>();
我们需要一个过滤器,该过滤器需要过滤集合并将结果返回给最终用户。假设我们有一个Filter类型对象的集合
class Filter
{
public string FieldName {get;set;}
public string FilterString {get;set;}
}
在代码的某个地方
List<Filter> userFilters = new List<Filter>();
因此,我们需要通过userFilters集合中定义的过滤器来过滤personList集合的内容。其中Filter.FieldName ==“ PersonName” || Filter.FieldName ==“ PersonAddress”。我如何以一种很酷的方式使用LINQ来做到这一点?诸如开关/外壳之类的解决方案,或者
我认为,可能是对PersonList的扩展方法,该方法根据FiledName确定要研究的Person的属性。还有别的吗?棘手的事情:)
谢谢。
参考方案
您可以使用Expression
类构建lambda表达式以创建正确的谓词。
public static Expression<Func<TInput, bool>> CreateFilterExpression<TInput>(
IEnumerable<Filter> filters)
{
ParameterExpression param = Expression.Parameter(typeof(TInput), "");
Expression lambdaBody = null;
if (filters != null)
{
foreach (Filter filter in filters)
{
Expression compareExpression = Expression.Equal(
Expression.Property(param, filter.FieldName),
Expression.Constant(filter.FilterString));
if (lambdaBody == null)
lambdaBody = compareExpression;
else
lambdaBody = Expression.Or(lambdaBody, compareExpression);
}
}
if (lambdaBody == null)
return Expression.Lambda<Func<TInput, bool>>(Expression.Constant(false));
else
return Expression.Lambda<Func<TInput, bool>>(lambdaBody, param);
}
使用此帮助程序方法,可以在任何IQueryable<T>
类上创建扩展方法,因此该方法适用于每个LINQ后端:
public static IQueryable<T> Where<T>(this IQueryable<T> source,
IEnumerable<Filter> filters)
{
return Queryable.Where(source, CreateFilterExpression<T>(filters));
}
...您可以这样称呼:
var query = context.Persons.Where(userFilters);
如果还想支持IEnumerable<T>
集合,则需要使用以下额外的扩展方法:
public static IEnumerable<T> Where<T>(this IEnumerable<T> source,
IEnumerable<Filter> filters)
{
return Enumerable.Where(source, CreateFilterExpression<T>(filters).Compile());
}
请注意,这仅适用于字符串属性。如果要过滤字段,则需要将Expression.Property
更改为Expression.Field
(或MakeMemberAccess
),并且如果需要支持字符串类型以外的其他类型,则必须提供更多类型信息以Expression.Constant
方法的CreateFilterExpression
部分。
我有一个包含成员Predicate的类,希望在Linq表达式中使用该类:using System.Linq; class MyClass { public bool DoAllHaveSomeProperty() { return m_instrumentList.All(m_filterExpression); } private IEnumerable&…
客户端反序列化为数组序列化字典<string,string>数据 - c#我有一个字典,该字典使用C#中的JavaScriptSerializer进行了序列化。在客户端,我有:"{"dd049eda-e289-4ca2-8841-4908f94d5b65":"2","ab969ac2-320e-42e1-b759-038eb7f57178":"5…
根据激活的Maven配置文件更新战争名称 - java在pom中,我有两个配置文件。测试1测试2现在,我希望根据激活的配置文件更改战争名称。预期结果激活test1配置文件后,战争名称应为prefix-test1.war。激活test1和test2时,战争名称应为prefix-test1-test2.war。如果没有激活任何配置文件,则战争名称应为prefix.war。我的POM文件....<?xml ve…
合并List <T>和List <Optional <T >> - java鉴于: List<Integer> integers = new ArrayList<>(Arrays.asList( 10, 12 )); List<Optional<Integer>> optionalIntegers = Arrays.asList( Optional.of(5), Optional.em…
将对象转换为List <object> - c#我看过类似的问题,但没有什么合适的。我有一个碰巧包含列表的对象。我想把它变成我可以列举的东西。例如:object listObject; // contains a List<Something> List<object> list; list = listObject as List<object>; // list c…