ChatGPT解决这个技术问题 Extra ChatGPT

为什么有些对象属性是 UnaryExpression 而有些是 MemberExpression?

根据我的 Select a model property using a lambda and not a string property name 问题的答案,希望将属性添加到集合中,如下所示:

var props = new ExportPropertyInfoCollection<JobCard>();
props.Include(model => model.BusinessInstallNumber).Title("Install No").Width(64).KeepZeroPadding(true);
props.Include(model => model.DeviceName).Title("Device").Width(70);
props.Include(model => model.DateRequested).Title("Request Date").Format("{0:dd/MM/yyyy}").Width(83);

我在 Include 方法中编写了以下代码:

public class PropertyCollection<T>
{
    public void Include(Expression<Func<T, object>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression != null)
        {
            var pes = new ExportPropertyInfoBuilder {Property = new ExportPropertyInfo {Property = memberExpression.Member as PropertyInfo}};
            Properties.Add(pes.Property.Property.Name, pes.Property);
            return pes;
    }

但是,在运行代码时,我发现一些 lambda 表达式按预期产生了 MemberExpression 值,而其他的则产生了 UnaryExpression 值。在使用 lambdas 添加所有属性之前,我必须将第一行代码更改为以下代码:

var memberExpression = expression.Body as MemberExpression ?? ((UnaryExpression) expression.Body).Operand as MemberExpression;

所有属性都是“简单”类型,即 POCO 业务对象中的 string、DateTime、int、bool 等。它们装饰有几个不同的 DataAnnotations 属性。

是什么导致我的示例中的某些 lambda 产生 MemberExpression 值和其他 UnaryExpression 值?在我的示例中,第一个 UnaryExpression 位于第三行,即 DateTime 属性,但布尔属性也会导致 UnaryExpressions。

UnaryExpression 表达式是否可能出现在可空列存在(或“不存在”)的情况下?
@leppie,我怀疑它在不可为空的列上。在我的示例中,第一个 UnaryExpression 位于 DateTime 上,而之前的 MemberExpression 位于字符串上。随后的 UnaryExpression 在布尔值上。
我会调查一下。我以前使用过(或者更确切地说是滥用)这样的表达式,从来没有遇到过问题,这意味着它总是 MemberExpression 否则我的代码会失败。您在哪个版本的 .NET 上运行?我还没有使用 .NET 4。
不确定这是否重要,但您能否包含 Include 所期望的表达式类型? (包括约束)

l
leppie

我想我知道问题是什么。您的表达式返回类型 object

如果将其更改为 Expression<Func<T, R>>,则应正确推断返回类型,并且不应发生 UnaryExpression(我将假设这是一些装箱操作)。

更新:

Include 的签名应为:

public void Include<T, R>(Expression<Func<T, R>> expression)

请原谅我的愚蠢,但是 R 应该是什么?我不能让它成为 MemberExpression,因为 MemberExression 在表达式的 Body 属性中。我同意 UnaryExpression 可能是因为拳击。
@ProfK:R 被简单地推断出来,它将是返回的属性的类型。你可能不会使用它,但你可能会:)
我想我看到了正在发生的事情。因为表达式返回类型是对象,所以它被装箱了。对于类型化的返回类型,这不会发生。谢谢@leppie!相信一个实用的人在这里提供帮助:-)
很好的答案。 Include 的签名不应该是: public void Include(Expression> expression) 因为 T 已经由 PropertyCollection 类定义。
@leppie T 泛型类型参数已在类级别定义,因此如果意图不同或冗余,则应使用不同的类型参数名称