Linq对象动态查询是可能的
本文关键字:查询 对象 动态 Linq | 更新日期: 2023-09-27 18:08:47
想知道是否可以使用linq对对象创建动态linq查询
我有一个屏幕,用户可以过滤多个东西。我需要建立一个内存过滤不使用数据库
那么让我们假设我有一个客户列表在内存中,我想筛选基于一些多选。
我认为一个可以传递谓词的方法可以达到这个目的,但显然不是。
我该怎么做?
如
public class Biz
{
public List<Customer> GetAllByName(string name)
{
return Repository.Find(x=> x.Name == name);
}
}
public class Repository
{
private List<Customer> internalCustomerList = GetAllCustomers();
public IEnumerable<Customer> Find(Expression<Func<T, bool>> predicate)
{
//How do I make below work in linq to object
return internalCustomerList.Where(predicate);//error here
}
}
另一种方法是传递字符串过滤器而不是谓词。动态LINQ库使这成为可能。
public IEnumerable<Customer> Find(string filter)
{
//filter would be something like "Age >= 20"
return internalCustomerList.Where(filter);
}
你可以这样做:
public class Biz
{
public List<Customer> GetAllByName(string name)
{
return Repository.Find(x=>x.Name == name);
}
}
public class Repository
{
private List<Customer> internalCustomerList = GetAllCustomers();
public static IEnumerable<Customer> Find(Func<T, bool> predicate)
{
return internalCustomerList.Where(predicate);
}
}
请注意List<T>
对Expression<Func<T, bool>>
没有过载。只有IQueryable<T>
有。详见http://msdn.microsoft.com/en-us/library/bb882637.aspx
IEnumerable<T>
仅具有委托扩展方法,即.Where(Func<T, bool> predicate)
使用.AsQueryable()
获得支持.Where(Expression<Func<T, bool>>)
的IQueryable<T>
我使用谓词构建器类为我的LINQ查询:
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
代码示例:
private static IQueryable<AppointmentDTO> FilterAppointmentData(IEnumerable<AppointmentDTO> data, AppointmentSearchDTO searchData)
{
var predicate = PredicateBuilder.True<AppointmentDTO>();
if (searchData.Status != null)
predicate = predicate.And(p => p.Status.Equals(Convert.ToInt32(searchData.Status)));
if (searchData.LastName != null)
predicate = predicate.And(p => p.LastName.ToLower().Contains(searchData.LastName.ToLower()));
if (searchData.File != null)
predicate = predicate.And(p => p.File.ToLower().Contains(searchData.File.ToLower()));
if (searchData.Doctor != null)
predicate = predicate.And(p => p.Doctor.ToLower().Contains(searchData.Doctor.ToLower()));
return data.AsQueryable().Where(predicate);
}
明白了:
http://www.albahari.com/nutshell/predicatebuilder.aspx干杯!
这绝对是可能的。您需要使用compile
方法将表达式转换为可调用的方法。我没有测试代码,但它应该非常接近以下内容:
public IEnumerable<Customer> Find(Expression<Func<Customer, bool>> predicate)
{
return internalCustomerList.Where(predicate.compile());
}