用参数代替子句lambda的操作员[英] replacing operator in Where clause Lambda with a parameter

本文是小编为大家收集整理的关于用参数代替子句lambda的操作员的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我想在" 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-part-1- using-the-linq-dynamic-query-library.aspx

和在这里下载

BB894665.aspx

它具有一个很好的表达语法,可让您表达很多不同的查询和操作.

请注意,根据查询,您可能会失去某种类型的安全性.可以使用操作的地方,但是编译器无法推断出从字符串中解析选择的lambda的任何类型的投影.您最终会以非传播的iQueryables而不是一般打字的方式进行测量.有时这是可以的,但是它确实可以阻止您以后在查询中使用通用扩展方法.

编辑以阐明非传播查询操作:该库包含一组非传播版本的查询扩展方法,这些版本采用表达式的字符串表示并在非代码iQeneric iqeerable上操作.如果您查看代码,那么如果您想要的不存在,则很容易看到如何编写这些代码.例如,我需要进行一个非传播的加入,只花了几个小时.

其他推荐答案

我找到了对您的问题的解决方案:

var test = dataContext.Interactions.DynamicWhere<Interaction,DateTime>("Created_Month", ExpressionType.LessThan, DateTime.Now);

您可以使用任何ExpressionType - 等于,小于,大于等等.它也将在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 });
        }
    }
}

本文地址:https://www.itbaoku.cn/post/1557134.html

问题描述

i want to replace operator(==, >= ,>...) in the clause where of linq lambda with parameter passed in method

the method:

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)

i want to replace == in the clause where with the parameter filter to obtain something like this

     var mod = from o in new GpsContext().Locals.Where(loc => loc.Date filter dt)

any body knows how to make it work ?

推荐答案

I think it's better to make dictionary out of string filters and corresponding delegates.

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));

        ...
     }
}

其他推荐答案

There is a good library for parsing strings into Lamdba expressions described here

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

and downloadable here

http://msdn2.microsoft.com/en-us/vcsharp/bb894665.aspx

It has a pretty good expression syntax that lets you express quite a lot of different queries and operations.

Be aware though that depending on the query, you may lose some type safety. Where operations are OK, but any kind of projection where the Select lambda is parsed from a string cannot be inferred by the compiler. This measn you end up with non-generic IQueryables rather than generically typed ones. Sometimes this is OK, but it does prevent you from using generic extension methods later on in the query.

Edit to clarify situation with non-generic query operations: The library contains a set of non-generic versions of the query extension methods that take string representations of expressions and operate on non-generic IQueryable. If you look at the code, it is pretty easy to see how to write these if the one you want isn't there. For example, I needed to do a non-generic Join and it only took a couple of hours.

其他推荐答案

I found a solution to your problem that works like this:

var test = dataContext.Interactions.DynamicWhere<Interaction,DateTime>("Created_Month", ExpressionType.LessThan, DateTime.Now);

You can use any ExpressionType - equals, less than, greater than, etc. and it will get translated to T-SQL if possible (so the filtering will be done on the server). It will also work in-memory on IEnumerables.

Here's the code:

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 });
        }
    }
}