Type成员的表达式导致不同的表达式(MemberExpression,UnaryExpression)

时间:2012-10-19 13:31:07

标签: c# .net lambda expression

描述

我有一个表达式指向我的类型的属性。 但它并不适用于每种房产类型。 “不代表”是指 它导致不同的表达类型。我以为它会产生一个 MemberExpression但事实并非如此。

intGuid会产生UnaryExpressionstringMemberExpression

我有点困惑;)

一些示例代码

我的班级

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

测试代码

Person p = new Person { Age = 16, Name = "John" };

Expression<Func<Person, object>> expression1 = x => x.Age;
// expression1.Body = UnaryExpression;

Expression<Func<Person, object>> expression2 = x => x.Name;
// expression2.Body = MemberExpression;

问题

我如何比较两个表达式并检查它们是否均值 相同类型和相同的属性?

更新,回答并完成样本

感谢用户 dasblinkenlight ,他让我走上正轨。

他提供了方法

private static MemberExpression GetMemberExpression<T>(
    Expression<Func<T,object>> exp
) {
    var member = expr.Body as MemberExpression;
    var unary = expr.Body as UnaryExpression;
    return member ?? (unary != null ? unary.Operand as MemberExpression : null);
}

我编写了以下扩展方法来比较GetMemberExpression的结果 方法并检查GetMemberExpression().Member.Name是否相同。

private static bool IsSameMember<T>(this Expression<Func<T, object>> expr1, Expression<Func<T, object>> expr2)
{
    var result1 = GetMemberExpression(expr1);
    var result2 = GetMemberExpression(expr2);

    if (result1 == null || result2 == null)
       return false;

    return result1.Member.Name == result2.Member.Name;
}

2 个答案:

答案 0 :(得分:73)

发生这种情况的原因是Age类型。为了强制将值类型返回到Func<Person,object>的表达式,编译器需要插入Convert(expr, typeof(object))UnaryExpression

对于string和其他引用类型,不需要框,因此返回“直接”成员表达式。

如果您想访问MemberExpression内的UnaryExpression,可以获取其操作数:

private static MemberExpression GetMemberExpression<T>(
    Expression<Func<T,object>> exp
) {
    var member = exp.Body as MemberExpression;
    var unary = exp.Body as UnaryExpression;
    return member ?? (unary != null ? unary.Operand as MemberExpression : null);
}

答案 1 :(得分:3)

我建议不要比较Member.Name字符串,而是直接比较PropertyInfo个实例的相等性,以避免在不同类中的两个属性共享相同名称时出现误报。

public static bool IsSameProperty<TSourceA, TSourceB, TPropertyA, TPropertyB>(
    Expression<Func<TSourceA, TPropertyA>> expA,
    Expression<Func<TSourceB, TPropertyB>> expB)
{
    MemberExpression memExpA = expA.Body as MemberExpression;
    MemberExpression memExpB = expB.Body as MemberExpression;

    if (memExpA == null || memExpB == null)
        return false;

    PropertyInfo propA = memExpA.Member as PropertyInfo;
    PropertyInfo propB = memExpB.Member as PropertyInfo;

    if (propA == null || propB == null)
        return false;

    return propA.Equals(propB);
}

只需将正确的值类型(而不是MemberExpression)指定为泛型类型{{1>,即可确保将lambda表达式编译为UnaryExpression而不是object。您的TResult表达式。

Expression<Func<T, TResult>>