为什么某些对象属性UnaryExpression和其他MemberExpression?


76

希望使用lambda而不是字符串属性名称问题来回答我的Select a model属性的问题,希望将属性添加到集合中,如下所示:

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业务对象中的字符串,DateTime,int,bool等。它们装饰有几种不同的DataAnnotations属性。

是什么原因导致我的示例中的某些lambda产生MemberExpression值而其他的UnaryExpression值呢?在我的示例中,第一个UnaryExpression在第三行上,即DateTime属性,但是布尔属性也导致UnaryExpressions


1
UnaryExpression表达式是否可能在可空的存在(或“不存在”)下发生?
2010年

@leppie,我怀疑它在不可为空的列上。在我的示例中,第一个UnaryExpression在DateTime上,而先前的MemberExpression在字符串上。随后的UnaryExpression在布尔上。
ProfK

我会调查一下。我以前使用过(或滥用)这样的表达式,并且从未遇到过问题,这意味着MemberExpression我的代码总是失败。您正在运行什么版本的.NET?我还没有使用.NET 4。
leppie

不知道这是否重要,但是您可以包括期望的期望表达类型Include吗?(包括限制条件)
leppie

Answers:


63

我想我知道问题出在哪里。您的表达式返回type object

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

更新:

的签名Include应为:

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

1
请原谅我的愚蠢,但是R应该是什么?我不能使其成为MemberExpression,因为MemberExression位于表达式的Body属性中。我同意UnaryExpression可能是因为拳击。
ProfK 2010年

4
@ProfK:简单地推断出R,它将是返回的属性的类型。您可能不会使用它,但您可能会:)
leppie

2
我想我知道发生了什么事。因为表达式返回类型是对象,所以将其装箱。对于类型化的返回类型,这不会发生。谢谢@leppie!相信一个
能干的

1
好答案。Include的签名不应为:public void Include <R>(Expression <Func <T,R >>表达式),因为T已由PropertyCollection类定义。
Xcalibur

3
@leppie T泛型类型参数已经在类级别定义,因此,如果意图不同或多余,则应使用不同的类型参数名称
Xcalibur
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.