gpt4 book ai didi

c# - 尝试为 linq 中的日期创建大于、等于或大于动态过滤器

转载 作者:太空狗 更新时间:2023-10-30 00:59:32 25 4
gpt4 key购买 nike

我一直在尝试为 Linq 创建一个表达式树过滤器,它采用 2 个日期和一串可能的值 { "lessthan", "equals", "morethan"}。我希望将调用格式化为类似 Query.Where(CompareDates(x => x.left, right, "less than"));

我有代码:

        public static IQueryable<TSource> CompareDates<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, DateTime?>> left,
DateTime? right,
string equality)
{
if (right == null || string.IsNullOrWhiteSpace(equality))
return source;

var p = left.Parameters.Single();
Expression member = p;

Expression leftExpression = Expression.Property(member, "left");
Expression rightParameter = Expression.Constant(right, typeof(DateTime));

BinaryExpression BExpression = null;
switch (equality)
{
case "lessthan":
BExpression = Expression.LessThan(leftExpression, rightParameter);
break;
case "equal":
BExpression = Expression.Equal(leftExpression, rightParameter);
break;
case "morethan":
BExpression = Expression.GreaterThan(leftExpression, rightParameter);
break;
default:
throw new Exception(String.Format("Equality {0} not recognised.", equality));
}

return source.Where(Expression.Lambda<Func<TSource, bool>>(BExpression, p));
}

不幸的是,它会产生错误“System.ArgumentException:在 SARRestAPI.Extensions 的 System.Linq.Expressions.Expression.Property(Expression expression, String propertyName) 中没有为类型‘Model’定义实例属性‘left’。 Expressions.CompareDates[TSource](IQueryable1 source, Expression1 src, DateTime supplied, String equality)"

有人知道为什么会这样吗?

最佳答案

开始吧;你想要做的是使用 .Body传入选择器的,而不是寻找 .left .意思是,给定输入选择器 x => x.Foo.Bar.Blap ,一个常量和一个比较,你想构造类似 x => x.Foo.Bar.Blap < someValue 的东西, 通过重用 x (参数,您已经在做)和正文 ( x.Foo.Bar.Blap )。

在代码中(注意这适用于任何 TValue ,而不仅仅是 DateTime ):

public enum Comparison
{
Equal,
NotEqual,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual
}
public static IQueryable<TSource> Compare<TSource, TValue>(
this IQueryable<TSource> source,
Expression<Func<TSource, TValue>> selector,
TValue value,
Comparison comparison)
{
Expression left = selector.Body;
Expression right = Expression.Constant(value, typeof(TValue));

BinaryExpression body;
switch (comparison)
{
case Comparison.LessThan:
body = Expression.LessThan(left, right);
break;
case Comparison.LessThanOrEqual:
body = Expression.LessThanOrEqual(left, right);
break;
case Comparison.Equal:
body = Expression.Equal(left, right);
break;
case Comparison.NotEqual:
body = Expression.NotEqual(left, right);
break;
case Comparison.GreaterThan:
body = Expression.GreaterThan(left, right);
break;
case Comparison.GreaterThanOrEqual:
body = Expression.GreaterThanOrEqual(left, right);
break;
default:
throw new ArgumentOutOfRangeException(nameof(comparison));
}

return source.Where(Expression.Lambda<Func<TSource, bool>>(body, selector.Parameters));
}

示例用法(此处使用 LINQ-to-Objects,但它也适用于其他 LINQ 后端):

var arr = new[] { new { X = 11 }, new { X = 12 }, new { X = 13 }, new { X = 14 } };
var source = arr.AsQueryable();

var filtered = source.Compare(x => x.X, 12, Comparison.GreaterThan);
foreach (var item in filtered)
{
Console.WriteLine(item.X); // 13 and 14
}

请注意,使用 C# vCurrent,您可以执行以下操作:

var body = comparison switch
{
Comparison.LessThan => Expression.LessThan(left, right),
Comparison.LessThanOrEqual => Expression.LessThanOrEqual(left, right),
Comparison.Equal => Expression.Equal(left, right),
Comparison.NotEqual => Expression.NotEqual(left, right),
Comparison.GreaterThan => Expression.GreaterThan(left, right),
Comparison.GreaterThanOrEqual => Expression.GreaterThanOrEqual(left, right),
_ => throw new ArgumentOutOfRangeException(nameof(comparison)),
};
return source.Where(Expression.Lambda<Func<TSource, bool>>(body, selector.Parameters));

你可能更喜欢。

关于c# - 尝试为 linq 中的日期创建大于、等于或大于动态过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57072538/

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