c# - PredicateBuilder 可重用 DateTime 谓词 setter

标签 c# predicatebuilder

我正在使用 PredicateBuilder生成动态搜索子句。在下面的示例代码中,有没有一种方法可以修改 SetDateTimePredicate,以便它可以用于 SomeType 上的任何 DateTime 属性?

Expression<Func<SomeType, bool>> somePredicate = null;
somePredicate = somePredicate.Or(
    SetDateTimePredicate(comparisonOperator, dateTime1, dateTime2));

private Expression<Func<SomeType, bool>> SetDateTimePredicate(
    Enums.ComparisonOperator comparison,
    DateTime dateTime1,
    DateTime dateTime2)
{
    switch (comparison)
    {
        case Enums.ComparisonOperator.IsLessThan:
            return p => p.SomeDateProperty < dateTime1;
        case Enums.ComparisonOperator.IsLessThanOrEqualTo:
            return p => p.SomeDateProperty <= dateTime1;
        case Enums.ComparisonOperator.IsGreaterThan:
            return p => p.SomeDateProperty  > dateTime1;
        case Enums.ComparisonOperator.IsGreaterThanOrEqualTo:
            return p => p.SomeDateProperty >= dateTime1;
        case Enums.ComparisonOperator.IsBetween:
            return p => p.SomeDateProperty >= dateTime1 
                     && p.SomeDateProperty <= dateTime2;
        default:
            return p => p.SomeDateProperty == dateTime1;
    }
}

我尝试了一种扩展方法但得到了这个错误:

System.NotSupportedException occurred
Message="Method 'Boolean Compare(System.DateTime, ComparisonOperator, System.DateTime, System.DateTime)' has no supported translation to SQL."    

扩展方法:

public static bool Compare(
    this DateTime dateToCompare,
    Enums.ComparisonOperator comparison,
    DateTime dateTime1,
    DateTime dateTime2)
{
    switch (comparison)
    {
        case Enums.ComparisonOperator.IsLessThan:
            return dateToCompare < dateTime1;
        case Enums.ComparisonOperator.IsLessThanOrEqualTo:
            return dateToCompare <= dateTime1;
        case Enums.ComparisonOperator.IsGreaterThan:
            return dateToCompare > dateTime1;
        case Enums.ComparisonOperator.IsGreaterThanOrEqualTo:
            return dateToCompare >= dateTime1;
        case Enums.ComparisonOperator.IsBetween:
            return dateToCompare >= dateTime1
                && dateToCompare <= dateTime2;
        default:
            return dateToCompare == dateTime1;
    }
}

带有扩展方法的示例:

somePredicate = somePredicate.Or(
    p => p.SomeDateProperty.Compare(comparisonOperator, dateTime1, dateTime2));

最佳答案

下面是一个通用的解决方案,它可以用于任何定义了比较运算符的类型,而不仅仅是 DateTime。我在 Enum.ComparisionOperator 类型上创建了方法和扩展方法。它会像这样使用:

Expression<Func<SomeType, bool>> somePredicate = comparisonOperator.Compare(
    (SomeType p) => p.SomeDateProperty, dateTime1, dateTime2));

方法定义为:

public static Expression<Func<TSource, bool>> Compare<TSource, TValue>(
    this Enums.ComparisonOperator comparison,
    Expression<Func<TSource, TValue>> source,
    TValue value1, TValue value2)
{
    var value1Expr = Expression.Constant(value1);
    var value2Expr = Expression.Constant(value2);
    var newExpr = comparison.CompareExpr(source.Body, value1Expr, value2Expr);
    return Expression.Lambda<Func<TSource, bool>>(newExpr, source.Parameters);
}
public static Expression CompareExpr(
    this Enums.ComparisonOperator comparison,
    Expression exprLeft,
    Expression exprRight1, Expression exprRight2)
{
    switch (comparison)
    {
        case Enums.ComparisonOperator.IsLessThan:
            return Expression.LessThan(exprLeft, exprRight1);
        case Enums.ComparisonOperator.IsLessThanOrEqualTo:
            return Expression.LessThanOrEqual(exprLeft, exprRight1);
        case Enums.ComparisonOperator.IsGreaterThan:
            return Expression.GreaterThan(exprLeft, exprRight1);
        case Enums.ComparisonOperator.IsGreaterThanOrEqualTo:
            return Expression.GreaterThanOrEqual(exprLeft, exprRight1);
        case Enums.ComparisonOperator.IsBetween:
            return Expression.AndAlso(
                Expression.GreaterThanOrEqual(exprLeft, exprRight1),
                Expression.LessThanOrEqual(exprLeft, exprRight2));
        default:
            return Expression.Equal(exprLeft, exprRight1);
    }
}

编辑:我将上面的方法更改为通用方法。

关于c# - PredicateBuilder 可重用 DateTime 谓词 setter ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10344551/

相关文章:

c# - Linq 如何在所有值都等于 null 或 0 时获取平均值? MVC

c# - 如何在 Prism 5.0 中为 TreeviewItem 编写 EventToCommand

c# - 使用 Linq 搜索实体列表中是否存在所有属性

mongodb - 有没有人能够成功地使用来自 albahari.com 的 PredicateBuilder 来对抗 MongoDB?

c# - 如何在 C# 中执行 C++ 逗号 + 三元运算符?

c# - 从 Windows 8 应用程序中生成的缓冲区播放声音

c# - 允许在 .NET TreeView 中进行多选

c# - PredicateBuilder:OR 条件嵌套在 .And() 中

C# 将表达式作为参数传递并使用 PredicateBuilder

java - 谓词 Java OR 问题