3

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

e.g. instead of

x => x.Name

the expression is

x => x

so if I had some class "Car" I could return the string "Car" instead of only being able to operate on its properties (e.g. Car.Colour)

The 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 want something like:

if (expression is SomeExpressionThatReturnsAnInstance)
{
    return (name of type of instance);
}
9
  • So you want to return object instead of property, is it ? Commented Apr 22, 2015 at 5:30
  • No, I want the name of the object's type, e.g. "Car" Commented Apr 22, 2015 at 5:47
  • if I had some class "Car" I could return the string "Car" instead --- x.ToString() or x.GetType().Name? Commented Apr 22, 2015 at 5:47
  • @TyCobb - nope, at this point I only have an expression. x.ToString() returns "x => x", and x.GetType().Name returns "Expression`1" Commented Apr 22, 2015 at 5:53
  • 2
    Where is GetMemberName called from? I think you don't even need the expression. You could use TypeOf(T) where T is the type of x, assuming you are calling it like it usually is. Commented Apr 22, 2015 at 6:31

4 Answers 4

1

I may be misunderstanding, but a direct x => x will be a ParameterExpression. Just add an additional test under your existing is MemberExpression test:

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
Sign up to request clarification or add additional context in comments.

2 Comments

methinks in OP x => x not ()=>x, so your solution possibly wrong
expression.NodeType is ExpressionType.Lambda
0

If you sure that expression like x=>x, so you even not need see in body, just get parameters like

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

also you can also add condition like

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

2 Comments

((LambdaExpression)expression).Parameters[0].Type.Name returns "Object"
@Mathew how you call it?
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));
    }

Comments

0

I've traced this back to the construction of the Expression. It doesn't really contain any instance information, and no way to get the type name.

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

So there's no way that a type name can be derived from an Expression that doesn't even have a type (other than object).

The method used to generate an expression that returns a property name:

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

2 Comments

I don't understand, you said that code like x => x.Name works. It can't work this way.
@Mathew, how you use this BuildExpression? You can't convert from LambdaExpression to Expression<Func<object, object>>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.