Using lambda expression to get property OR type name

How can I adapt the method below to work when the lambda expression refers to the actual instance itself?

eg. instead

x => x.Name

      

expression

x => x

      

so if I had some kind of class "Car" I could return the string "Car" and not only work with its properties (eg Car.Colour)

Method:

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

      

i.e. I need something like:

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

      

+3


source to share


4 answers


I've traced this back to building the expression. It does not contain any information about the instance and has no way of getting the type name.

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

      

So there is no way that a type name can be inferred from an expression that doesn't even have a type (other than an object).



Method used to create an expression that returns the name of the property:

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

      

0


source


I may be wrong, but it x => x

will be direct ParameterExpression

. Just add an additional test to your existing test is MemberExpression

:

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

      

Using this code:

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


source


If you are sure that an expression like x => x, so you don't even need to see in the body, just get parameters like

((LambdaExpression)expression).Parameters.First().Type.Name

      

also you can add a condition like

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

      

0


source


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

      

0


source







All Articles