假设我们有一个Person对象的集合
class Person
{
public string PersonName {get;set;}
public string PersonAddress {get;set;}
}以及代码定义集合中的某个位置
List<Person> pesonsList = new List<Person>();我们需要一个过滤器,它需要过滤集合并将结果返回给最终用户。假设我们有一个过滤器类型对象的集合
class Filter
{
public string FieldName {get;set;}
public string FilterString {get;set;}
}在我们的代码中
List<Filter> userFilters = new List<Filter>(); 因此,我们需要通过在personsList集合中定义的过滤器过滤userFilters集合的内容。其中的Filter.FieldName == "PersonName“\x Filter.FieldName == "PersonAddress"。我怎么能用LINQ以一种很酷的方式做到这一点呢?解决方案,如开关/案例,或可能是,我认为,在personsList上的扩展方法,从FiledName确定的人的性质调查,是已知的。还有别的吗?一些棘手的问题:)谢谢。
发布于 2009-08-24 21:33:21
您可以构建一个lambda表达式来使用Expression类创建一个正确的谓词。
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));
}您可以这样调用...which:
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),如果需要支持字符串属性以外的其他类型,则必须向CreateFilterExpression方法的Expression.Constant部分提供更多的类型信息。
发布于 2009-08-24 21:17:51
你可以通过反射完成:
IQueryable<Person> filteredPersons = personsList.AsQueryable();
Type personType = typeof(Person);
foreach(Filter filter in userFilters) {
filteredPersons = filteredPersons.Where(p => (string)personType.InvokeMember(filter.FieldName, BindingFlags.GetProperty, null, p, null) == filter.FilterString);
}(未编译,但应沿着正确的轨道进行)
发布于 2009-08-24 21:40:40
你就不能就这么做
personList.Where(x => x.PersonName == "YourNameHere").ToList() ?https://stackoverflow.com/questions/1324774
复制相似问题