Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Linq到对象动态查询有可能吗?_C#_Linq - Fatal编程技术网

C# Linq到对象动态查询有可能吗?

C# Linq到对象动态查询有可能吗?,c#,linq,C#,Linq,想知道是否可以使用linq to对象创建动态linq查询 我有一个屏幕,用户可以在其中过滤多种内容。 我需要建立一个不使用数据库的内存过滤 因此,让我们假设我在内存中有一个客户列表,我想根据一些多重选择进行筛选 我认为一个可以传递谓词的方法可以做到这一点,但显然不行 我怎么做 乙二醇 公共类业务 { 公共列表GetAllByName(字符串名称) { 返回Repository.Find(x=>x.Name==Name); } } 公共类存储库 { 私有列表internalCustomerList

想知道是否可以使用linq to对象创建动态linq查询

我有一个屏幕,用户可以在其中过滤多种内容。 我需要建立一个不使用数据库的内存过滤

因此,让我们假设我在内存中有一个客户列表,我想根据一些多重选择进行筛选

我认为一个可以传递谓词的方法可以做到这一点,但显然不行

我怎么做

乙二醇

公共类业务
{
公共列表GetAllByName(字符串名称)
{
返回Repository.Find(x=>x.Name==Name);
}
}
公共类存储库
{
私有列表internalCustomerList=GetAllCustomers();
公共IEnumerable查找(表达式谓词)
{
//如何在linq to object中使下面的工作正常
返回internalCustomerList.Where(谓词);//此处出错
}
}
您可以执行以下操作:

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);
    }
}
公共类业务
{
公共列表GetAllByName(字符串名称)
{
返回Repository.Find(x=>x.Name==Name);
}
}
公共类存储库
{
私有列表internalCustomerList=GetAllCustomers();
公共静态IEnumerable Find(Func谓词)
{
返回internalCustomerList.Where(谓词);
}
}
请注意,
列表
没有表达式的重载。只有
IQueryable
具有。更多信息,请参见

IEnumerable
仅具有带有委托的扩展方法,也称为
。其中(Func谓词)


使用
.AsQueryable()
获取支持
.Where(表达式)
IQueryable
。您需要使用
compile
方法将表达式转换为可调用方法。我没有测试代码,但应该非常接近以下内容:

public IEnumerable<Customer> Find(Expression<Func<Customer, bool>> predicate)
{
    return  internalCustomerList.Where(predicate.compile());
}
public IEnumerable Find(表达式谓词)
{
返回internalCustomerList.Where(predicate.compile());
}

另一种方法是传递字符串筛选器而不是谓词。这使得这成为可能

public IEnumerable<Customer> Find(string filter)
{
    //filter would be something like "Age >= 20"
    return internalCustomerList.Where(filter);
}
公共IEnumerable查找(字符串筛选器)
{
//过滤器将类似于“年龄>=20”
返回internalCustomerList.Where(过滤器);
}

我使用谓词生成器类进行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);
    }
}
使用系统;
使用System.Linq;
使用System.Linq.Expressions;
使用System.Collections.Generic;
公共静态类谓词生成器
{
公共静态表达式True(){return f=>True;}
公共静态表达式False(){return f=>False;}
公共静态表达式或(此表达式expr1,
表达式expr2)
{
var invokedExpr=Expression.Invoke(expr2,expr1.Parameters.Cast());
返回表达式.Lambda
(Expression.OrElse(expr1.Body,invokedExpr),expr1.Parameters);
}
公共静态表达式和(此表达式expr1,
表达式expr2)
{
var invokedExpr=Expression.Invoke(expr2,expr1.Parameters.Cast());
返回表达式.Lambda
(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);
        }
私有静态IQueryable


干杯

为什么您的
Find
方法返回
Expression>
而不是
IEnumerable
?编辑以返回IEnumerable您得到了什么错误?可以执行与上面类似的操作,因此我很好奇错误是什么。@AdamJones我得到的是“方法的类型参数”IEnumerableSystem.Linq.Enumerable。其中(此bla…)无法从用法推断。+1我将此库与JQGrid结合使用,非常强大。谢谢。为什么我可以做公共IEnumerable查找(Func谓词){return\u internalCustomerList.Where(谓词);}但是如果我做公共IEnumerable查找(Func谓词){return internalCustomerList.Where(谓词);}会给我一个错误。我需要一些强制转换,但不确定我认为您需要的是
公共静态IEnumerable Find(Func谓词)
(注意Find方法上的泛型。这应该允许您返回
IEnumerable
。您有一个如何实现AsQueryable的示例吗谢谢
。AsQueryable()
是所有
IEnumerable
上的标准扩展方法,使用Linq to对象。无需实现任何功能。感谢您的回复。出现错误“为lambda声明提供的参数数量不正确”谷歌搜索,但似乎无法解决我已经尝试并更正了我的代码。事情比我想象的还要简单。
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);
        }