开始了;你想做的是使用.Body
传入选择器的,而不是寻找.left
。意思是,给定一个输入选择器x => x.Foo.Bar.Blap
、一个常量和一个比较,你想要构建类似的东西x => x.Foo.Bar.Blap < someValue
, by reusing这俩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));
您可能会更喜欢。