gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 14:49:28 24 4
gpt4 key购买 nike

我想使用“条件”对象动态构建 LinqToSQL 和 EntityFramework 查询子句,并在必要时利用 C# In a Nutshell PredicateBuilder (http://www.albahari.com/nutshell/predicatebuilder.aspx)

澄清一下——我不明白如何创建 C# 表达式 ;o)

过滤器运算符和值被定义为我的“查询条件”类的属性:

public class QueryCriteria
{
public DateTimeFilter DateTimeCompleted { get; set; }
}

“过滤器”定义为:

public class DateTimeFilter
{
public FilterOperator FilterOperator { get; set; }

public DateTime FilterToken { get; set; }
}

“过滤器运算符”是一个普通的 C# 枚举:

public enum FilterOperator : int
{
ExactMatch = 1,
BeginsWith = 2,
Contains = 3,
EndsWith = 4,
GreaterThan = 5,
GreaterThanOrEqualTo = 6,
LessThan = 7,
LessThanOrEqualTo = 8,
}

我想使用以下方法在我的存储库中动态构建我的 LinqToSQL 和 EntityFramework 查询:

if (criteria.DateTimeCompleted != null)
{
var predicate = PredicateBuilder.True(query);

switch (criteria.DateTimeCompleted.FilterOperator)
{
case FilterOperator.ExactMatch:
predicate = predicate.And(p => string.Equals(p.DateTimeCompleted.Value, criteria.DateTimeCompleted.FilterToken));
break;

case FilterOperator.GreaterThan:
predicate = predicate.And(p => p.DateTimeCompleted.Value > criteria.DateTimeCompleted.FilterToken);
break;

case FilterOperator.GreaterThanOrEqualTo:
predicate = predicate.And(p => p.DateTimeCompleted.Value >= criteria.DateTimeCompleted.FilterToken);
break;

case FilterOperator.LessThan:
predicate = predicate.And(p => p.DateTimeCompleted.Value < criteria.DateTimeCompleted.FilterToken);
break;

case FilterOperator.LessThanOrEqualTo:
predicate = predicate.And(p => p.DateTimeCompleted.Value <= criteria.DateTimeCompleted.FilterToken);
break;

default:
throw new InvalidOperationException("Can't use the specified filter operator on a DateTime.");
}

query = query.Where(predicate);
}

以上都有效,但我希望我的代码是 DRY,当我将另一个属性添加到我的条件(例如 DateTimeStarted)时,我不希望我的存储库为新属性复制上面的代码。

所以我想将上面的代码简化为:

query = query.Where(criteria.DateTimeCompleted.GetPredicate(query, p => p.DateTimeCompleted.Value));

这可能吗?如果可能的话如何?

最佳答案

绝对可以(不需要PredicateBuilder)。您只需将支持的 FilterOperator 映射到相应的 Expression

这是执行此操作的自定义扩展方法:

public static class QueryableExtensions
{
public static IQueryable<T> Where<T>(this IQueryable<T> source, DateTimeFilter filter, Expression<Func<T, DateTime>> target)
{
if (filter == null) return source;
var left = target.Body;
var right = Expression.Constant(filter.FilterToken);
Expression condition;
switch (filter.FilterOperator)
{
case FilterOperator.ExactMatch:
condition = Expression.Equal(left, right);
break;

case FilterOperator.GreaterThan:
condition = Expression.GreaterThan(left, right);
break;

case FilterOperator.GreaterThanOrEqualTo:
condition = Expression.GreaterThanOrEqual(left, right);
break;

case FilterOperator.LessThan:
condition = Expression.LessThan(left, right);
break;

case FilterOperator.LessThanOrEqualTo:
condition = Expression.LessThanOrEqual(left, right);
break;

default:
throw new InvalidOperationException("Can't use the specified filter operator on a DateTime.");
}
var predicate = Expression.Lambda<Func<T, bool>>(condition, target.Parameters);
return source.Where(predicate);
}
}

和示例用法:

query = query.Where(criteria.DateTimeCompleted, p => p.DateTimeCompleted.Value);

关于C# 将表达式作为参数传递并使用 PredicateBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38655112/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com