【问题标题】:Declaring literal dates in lambda expression在 lambda 表达式中声明文字日期
【发布时间】:2016-01-29 16:59:05
【问题描述】:

我目前正在开发一个简单的引擎,它可以从不同的类(使用反射和表达式工厂)生成 lamda 表达式。

我在尝试对我的引擎进行一些单元测试时遇到问题。

我使用我的引擎生成 lambda 表达式,然后将生成的 lambda 与“手工制作”的 lambda 表达式进行比较。问题是当我在 lambda 表达式中使用 DateTime 时。反射生成的 lambda 包含一个“硬编码”日期,而在“手工制作”的 lambda 表达式中,我必须使用“new DateTime(...)”。

因此单元测试失败并显示以下消息(我删除了消息以仅保留有趣的部分):

预期: (...) AndAlso (x.Date

但是是: (...) AndAlso (x.Date

我的断言如下:

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 框架管理)。


编辑:

这是一个显示我的问题的简单小提琴: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);

【问题讨论】:

  • “生成 lambda 表达式”究竟是什么意思?您的意思是“生成表达式树”吗?它们是非常不同的东西...... lambda 表达式是 C# 语法的一个元素......如果你能展示一个简短但完整的程序来展示问题,那将会很有帮助......

标签: c# .net lambda nunit


【解决方案1】:

假设您真的想生成一个带有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))

如果您在多个地方需要它,您可以很容易地将它构建到实用方法中。

【讨论】:

  • 这正是我使用反射生成表达式树的方式。问题是使用基本的硬编码 lambda 表达式生成相同的东西,以便为自动生成进行简单易读的测试。正如你所问,我用一个简单的小提琴更新了我的问题。
  • @PaulDS:请在问题本身中包含示例,而不是小提琴。但基本上我怀疑辅助方法是你能得到的最好的方法。
猜你喜欢
  • 1970-01-01
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多