使用 lambda 表达式获取 属性 或类型名称

Using lambda expression to get property OR type name

当 lambda 表达式引用实际实例本身时,我如何调整下面的方法来工作?

例如而不是

x => x.Name

表达式是

x => x

所以如果我有一些 class "Car" 我可以 return 字符串 "Car" 而不是只能对其属性进行操作(例如 Car.Colour)

方法:

public static string GetMemberName(Expression expression)
    {
        if (expression is LambdaExpression)
            expression = ((LambdaExpression)expression).Body;

        if (expression is MemberExpression)
        {
            var memberExpression = (MemberExpression)expression;
            if (memberExpression.Expression.NodeType ==
                ExpressionType.MemberAccess)
            {
                return GetMemberName(memberExpression.Expression)
                       + "."
                       + memberExpression.Member.Name;
            }
            return memberExpression.Member.Name;
        }


        if (expression is UnaryExpression)
        {
            var unaryExpression = (UnaryExpression)expression;

            if (unaryExpression.NodeType != ExpressionType.Convert)
                throw new Exception(string.Format(
                    "Cannot interpret member from {0}",
                    expression));
            return GetMemberName(unaryExpression.Operand);
        }
        throw new Exception(string.Format(
            "Could not determine member from {0}",
            expression));
    }

即我想要这样的东西:

if (expression is SomeExpressionThatReturnsAnInstance)
{
    return (name of type of instance);
}

可能是我误会了,直接x => x就是ParameterExpression。只需在您现有的 is MemberExpression 测试下添加一个额外的测试:

if (expression is MemberExpression)
{
    // As-is
}
// New condition
if (expression is ParameterExpression)
{
    return expression.Type.Name;
}

使用此代码:

class Car { public string Color { get; set; }}

Expression<Func<Car, string>> expr1 = x => x.Color;
Expression<Func<Car, Car>> expr2 = x => x;

Console.WriteLine(GetMemberName(expr1));
> Color
Console.WriteLine(GetMemberName(expr2));
> Car

如果你确定像 x=>x 这样的表达式,那么你甚至不需要在正文中看到,只需获取像

这样的参数
((LambdaExpression)expression).Parameters.First().Type.Name

你也可以添加条件如

if(expression is ParameterExpression){
    return ((ParameterExpression)expression).Type
}

我已经将其追溯到表达式的构造。它实际上不包含任何实例信息,也无法获取类型名称。

static Expression<Func<object, object>> thisObject = x => x;

因此,无法从甚至没有类型(对象除外)的表达式派生类型名称。

用于生成returns一个属性名称的表达式的方法:

LambdaExpression BuildExpression(Type rootType, string propertyName)
    {
        try
        {
            var properties = propertyName.Split('.');
            ParameterExpression arg = Expression.Parameter(rootType, "x");
            Expression expr = arg;
            foreach (string property in properties)
            {
                PropertyInfo propertyInfo = rootType.GetProperty(property);
                if (propertyInfo == null)
                    return null;
                expr = Expression.Property(expr, propertyInfo);
                rootType = propertyInfo.PropertyType;
            }
            return Expression.Lambda(expr, arg);
        }
        catch (System.Exception ex)
        {
            return null;
        }
    }
//Use generics for more information!
public static string GetMemberName<T, TValue>(Expression<Func<T, TValue>> expression)
    {
        if (expression is LambdaExpression)
            expression = ((LambdaExpression)expression).Body;

        if (expression is MemberExpression)
        {
            var memberExpression = (MemberExpression)expression;
            if (memberExpression.Expression.NodeType ==
                ExpressionType.MemberAccess)
            {
                return GetMemberName(memberExpression.Expression)
                       + "."
                       + memberExpression.Member.Name;
            }
            return memberExpression.Member.Name;
        }

        //Magic part...
        if (typeof(T) == typeof(TValue))
        {
             return typeof(T).Name;
        }

        if (expression is UnaryExpression)
        {
            var unaryExpression = (UnaryExpression)expression;

            if (unaryExpression.NodeType != ExpressionType.Convert)
                throw new Exception(string.Format(
                    "Cannot interpret member from {0}",
                    expression));
            return GetMemberName(unaryExpression.Operand);
        }
        throw new Exception(string.Format(
            "Could not determine member from {0}",
            expression));
    }