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

时间:2015-04-22 05:25:48

标签: c# lambda expression-trees

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

e.g。而不是

x => x.Name

表达式是

x => x

所以,如果我有一些课程" Car"我可以退回字符串" 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);
}

4 个答案:

答案 0 :(得分:1)

我可能会误解,但直接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

答案 1 :(得分:0)

如果您确定表达式如 x =&gt; x ,那么您甚至不需要在body中查看,只需获取

之类的参数
((LambdaExpression)expression).Parameters.First().Type.Name

你也可以添加像

这样的条件
if(expression is ParameterExpression){
    return ((ParameterExpression)expression).Type
}

答案 2 :(得分:0)

我已将此追溯到构建表达式。它并不真正包含任何实例信息,也无法获取类型名称。

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

因此,不能从一个甚至没有类型(不是对象)的表达式派生类型名称。

用于生成返回属性名称的表达式的方法:

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;
        }
    }

答案 3 :(得分:0)

//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));
    }