用参数替换Where子句Lambda中的运算符
本文关键字:运算符 Lambda 子句 参数 替换 Where | 更新日期: 2023-09-27 18:24:04
我想用方法中传递的参数替换linq lambda子句中的运算符(==,>=,>…)
方法:
public IEnumerable<Localisation> GetByFiltre(string filter, string valeurDate1)
/*
filter has the value of an operator:
>
==
!=
>=
<=
*/
DateTime dt = Convert.ToDateTime(valeurDate1);
var mod = from o in new GpsContext().Locals.Where(loc => loc.Date == dt)
我想用参数筛选器替换子句中的==获得类似的东西
var mod = from o in new GpsContext().Locals.Where(loc => loc.Date filter dt)
任何人都知道如何让它发挥作用?
我认为最好用字符串过滤器和相应的委托来制作字典。
class YourClass
{
static readonly Dictionary<string, Func<DateTime, DateTime, bool>> s_filters = new Dictionary<string, Func<DateTime, DateTime, bool>>
{
{ ">", new Func<DateTime, DateTime, bool>((d1, d2) => d1 > d2) }
{ "==", new Func<DateTime, DateTime, bool>((d1, d2) => d1 == d2) }
{ "!=", new Func<DateTime, DateTime, bool>((d1, d2) => d1 != d2) }
{ ">=", new Func<DateTime, DateTime, bool>((d1, d2) => d1 >= d2) }
{ "<=", new Func<DateTime, DateTime, bool>((d1, d2) => d1 <= d2) }
};
public IEnumerable<Localisation> GetByFiltre(string filter, string valeurDate1)
{
...
DateTime dt = Convert.ToDateTime(valeurDate1);
var filterDelegate = s_filters[filter];
var mod = from o in new GpsContext().Locals.Where(loc => filterDelegate(loc.Date,dt));
...
}
}
有一个很好的库可以将字符串解析为此处描述的Lamdba表达式
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
并可在此处下载
http://msdn2.microsoft.com/en-us/vcsharp/bb894665.aspx
它有一个非常好的表达式语法,可以让你表达很多不同的查询和操作。
请注意,根据查询的不同,您可能会失去一些类型安全性。Where操作可以,但编译器无法推断从字符串解析Select lambda的任何类型的投影。这意味着您最终得到的是非泛型IQueryable,而不是泛型类型的IQueryables。有时这是可以的,但它确实会阻止您稍后在查询中使用泛型扩展方法。
编辑以澄清非通用查询操作的情况:库包含一组非通用版本的查询扩展方法,这些方法采用表达式的字符串表示形式,并对非通用IQueryable进行操作。如果你看一下代码,很容易就能知道如果你想要的代码不在那里,该怎么写。例如,我需要做一个非通用的Join,它只花了几个小时。
我找到了一个解决您问题的方法,它的工作原理如下:
var test = dataContext.Interactions.DynamicWhere<Interaction,DateTime>("Created_Month", ExpressionType.LessThan, DateTime.Now);
您可以使用任何ExpressionType
-等于、小于、大于等,如果可能的话,它将被转换为T-SQL(因此过滤将在服务器上完成)。它也将在IEnumerables
上的内存中工作。
这是代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace WindowsFormsApplication1
{
public static class GenericFilterExtension
{
public static IQueryable<TRow> DynamicWhere<TRow,TColumn>(this IQueryable<TRow> input, string field, ExpressionType binaryOperator, TColumn value)
{
var exp = MakeWhereLambda<TRow, TColumn>(field, binaryOperator, value) as Expression<Func<TRow, bool>>;
return input.Where(exp);
}
public static IEnumerable<TRow> DynamicWhere<TRow, TColumn>(this IEnumerable<TRow> input, string field, ExpressionType binaryOperator, TColumn value)
{
var exp = MakeWhereLambda<TRow, TColumn>(field, binaryOperator, value).Compile() as Func<TRow, bool>;
return input.Where(exp);
}
private static LambdaExpression MakeWhereLambda<TRow, TColumn>(string field, ExpressionType binaryOperator, TColumn value)
{
var param = Expression.Parameter(typeof(TRow), "n");
var op = Expression.MakeBinary(binaryOperator, Expression.Property(param, field), Expression.Constant(value));
return Expression.Lambda(op, new ParameterExpression[] { param });
}
}
}
您可以传入作为where子句的函数,例如
public IEnumerable<Localisation> GetByFiltre(Func<IEnumerable<localisation>, IEnumerable<localisation>> whereClause)
{
/*
filter has the value of an operator:
>
==
!=
>=
<=
*/
DateTime dt = Convert.ToDateTime(valeurDate1);
var mod = whereClause(new GpsContext().Locals);
}
并称之为:
GetByFiltre(f => f.Where(d => d.Date > SomeDate));
过滤器应该包含"=="、">="等?你可以用传统的方法分析过滤字符串:
var mod = from o in new GpsContext().Locals.Where(loc =>
{
switch(filter)
{
case "==":
return loc.Date == dt;
case ">=":
return loc.Date >= dt;
// ...
}
})