Linq对象动态查询是否可能?

时间:2011-09-17 15:42:00

标签: c# linq

想知道是否可以使用linq to objects创建动态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
    }
}

5 个答案:

答案 0 :(得分:6)

另一种方法是传递字符串过滤器而不是谓词。 Dynamic LINQ Library使这成为可能。

public IEnumerable<Customer> Find(string filter)
{
    //filter would be something like "Age >= 20"
    return internalCustomerList.Where(filter);
}

答案 1 :(得分:1)

你可以这样做:

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

了解更多信息

答案 2 :(得分:1)

IEnumerable<T>只有代表的扩展方法,即.Where(Func<T, bool> predicate)

使用.AsQueryable()获取支持IQueryable<T>

.Where(Expression<Func<T, bool>>)

答案 3 :(得分:1)

绝对有可能。您需要使用compile方法将表达式转换为可调用方法。我没有测试过代码,但它应该非常接近以下内容:

public IEnumerable<Customer> Find(Expression<Func<Customer, bool>> predicate)
{
    return  internalCustomerList.Where(predicate.compile());
}

答案 4 :(得分:1)

我为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

干杯!