在 lambda 表达式中声明文字日期
Declaring literal dates in lambda expression
我目前正在开发一个简单的引擎,它从不同的类(使用反射和表达式工厂)生成 lamda 表达式。
我在尝试对我的引擎进行一些单元测试时遇到问题。
我使用我的引擎生成 lambda 表达式,然后将生成的 lambda 与“手工制作”的 lambda 表达式进行比较。问题是当我在我的 lambda 表达式中使用 DateTime 时。用反射生成的 lambda 包含一个“硬编码”日期,而在“手工制作”的 lambda 表达式中,我必须使用“new DateTime(...)”。
因此单元测试失败并显示以下消息(我删除了消息以仅保留有趣的部分):
Expected: < x => (...) AndAlso (x.Date <= new DateTime(2015, 1, 1)))>
But was: < x => (...) AndAlso (x.Date <= 01/01/2015 00:00:00))>
我的断言如下:
Assert.AreEqual(expectedWhere, request.Filter);
其中“expectedWhere”是“手工制作”的 lambda,“request.Filter”是生成的 lambda。
是否有解决方案 (like in VB.NET) 来创建我的 lambda 表达式:
Expression<Func<Model, bool>> expectedWhere = x => (...) && (x.Date <= [01/01/2015 00:00:00])
我已经测试过使用外部变量 DateTime.Now 或常量(不受 .NET 框架管理)。
编辑:
这是一个简单的 fiddle 显示我的问题:https://dotnetfiddle.net/fKccY3
代码:
ParameterExpression param = Expression.Parameter(typeof(Model), "x");
var property = Expression.Property(param, "Date");
ConstantExpression constant = Expression.Constant(new DateTime(2015, 1, 1), typeof(DateTime));
Expression finalExpression = Expression.LessThanOrEqual(property, constant);
var tree = Expression.Lambda<Func<Model, bool>>(finalExpression, param);
Console.WriteLine(tree);
Expression<Func<Model, bool>> handMaidExpression = x => x.Date == new DateTime(2015, 1, 1);
Console.WriteLine(handMaidExpression);
假设您真的是想生成一个带有 ConstantExpression
的合适的表达式树,我认为您在使用实际的 lambda 表达式时会遇到麻烦。但是,您可以通过使用 lambda 表达式为它的 rest 构建一个表达式树,然后手动完成其余的操作,从而相当轻松地构建相关的表达式树。这是一个简短但完整的示例:
using System;
using System.Linq.Expressions;
public class Model
{
public string Name { get; set; }
public DateTime Date { get; set; }
}
public class Test
{
public static void Main()
{
Expression<Func<Model, bool>> original = x => x.Name == "Fred";
var parameter = original.Parameters[0];
var dateClause = Expression.LessThanOrEqual(
Expression.Property(parameter, "Date"),
Expression.Constant(new DateTime(2015, 1, 1), typeof(DateTime)));
var combined = Expression.AndAlso(original.Body, dateClause);
var tree = Expression.Lambda<Func<Model, bool>>(combined, parameter);
Console.WriteLine(tree);
}
}
输出:
x => ((x.Name == "Fred") AndAlso (x.Date <= 01/01/2015 00:00:00))
如果您在多个地方需要它,您可以很容易地将它构建到一个实用方法中。
我目前正在开发一个简单的引擎,它从不同的类(使用反射和表达式工厂)生成 lamda 表达式。
我在尝试对我的引擎进行一些单元测试时遇到问题。
我使用我的引擎生成 lambda 表达式,然后将生成的 lambda 与“手工制作”的 lambda 表达式进行比较。问题是当我在我的 lambda 表达式中使用 DateTime 时。用反射生成的 lambda 包含一个“硬编码”日期,而在“手工制作”的 lambda 表达式中,我必须使用“new DateTime(...)”。
因此单元测试失败并显示以下消息(我删除了消息以仅保留有趣的部分):
Expected: < x => (...) AndAlso (x.Date <= new DateTime(2015, 1, 1)))>
But was: < x => (...) AndAlso (x.Date <= 01/01/2015 00:00:00))>
我的断言如下:
Assert.AreEqual(expectedWhere, request.Filter);
其中“expectedWhere”是“手工制作”的 lambda,“request.Filter”是生成的 lambda。
是否有解决方案 (like in VB.NET) 来创建我的 lambda 表达式:
Expression<Func<Model, bool>> expectedWhere = x => (...) && (x.Date <= [01/01/2015 00:00:00])
我已经测试过使用外部变量 DateTime.Now 或常量(不受 .NET 框架管理)。
编辑:
这是一个简单的 fiddle 显示我的问题:https://dotnetfiddle.net/fKccY3
代码:
ParameterExpression param = Expression.Parameter(typeof(Model), "x");
var property = Expression.Property(param, "Date");
ConstantExpression constant = Expression.Constant(new DateTime(2015, 1, 1), typeof(DateTime));
Expression finalExpression = Expression.LessThanOrEqual(property, constant);
var tree = Expression.Lambda<Func<Model, bool>>(finalExpression, param);
Console.WriteLine(tree);
Expression<Func<Model, bool>> handMaidExpression = x => x.Date == new DateTime(2015, 1, 1);
Console.WriteLine(handMaidExpression);
假设您真的是想生成一个带有 ConstantExpression
的合适的表达式树,我认为您在使用实际的 lambda 表达式时会遇到麻烦。但是,您可以通过使用 lambda 表达式为它的 rest 构建一个表达式树,然后手动完成其余的操作,从而相当轻松地构建相关的表达式树。这是一个简短但完整的示例:
using System;
using System.Linq.Expressions;
public class Model
{
public string Name { get; set; }
public DateTime Date { get; set; }
}
public class Test
{
public static void Main()
{
Expression<Func<Model, bool>> original = x => x.Name == "Fred";
var parameter = original.Parameters[0];
var dateClause = Expression.LessThanOrEqual(
Expression.Property(parameter, "Date"),
Expression.Constant(new DateTime(2015, 1, 1), typeof(DateTime)));
var combined = Expression.AndAlso(original.Body, dateClause);
var tree = Expression.Lambda<Func<Model, bool>>(combined, parameter);
Console.WriteLine(tree);
}
}
输出:
x => ((x.Name == "Fred") AndAlso (x.Date <= 01/01/2015 00:00:00))
如果您在多个地方需要它,您可以很容易地将它构建到一个实用方法中。