1

I want to get the string representation of a lambda Func<> Expression to get the Property Path. I have this example

Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses["Address"];

and i am expecting a string

"EmployeeInfo.Addresses["Address"]"

when i do _xxx.ToString(); i'll just do some string parsing and i can get the result above.

My problem is when i do

var _addrName = "Address";
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses[_addrName];

i got a very long string

"EmployeeInfo.Addresses.get_Item(value(UnitTestProj.UnitTest.AnyTest+<>c__DisplayClass0)._addr)"

which is very hard to manipulate to come up with "EmployeeInfo.Addresses["Address"]"

Is there any way to achieve my purpose?

TIA

1 Answer 1

3

This should get you pretty far - it's very hacky but I don't think there's a way around it:

Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses[address];
WriteLine(ExprToString(_xxx)); //e.EmployeeInfo.Addresses[address]

_xxx = x => x.EmployeeInfo.Addresses["XYZ"]; 
WriteLine(ExprToString(_xxx)); //x.EmployeeInfo.Addresses["XYZ"]

_xxx = y => y.EmployeeInfo.Addresses[null];
WriteLine(ExprToString(_xxx)); //y.EmployeeInfo.Addresses[null]

_xxx = z => z.EmployeeInfo.Name;
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Name

_xxx = z => z.EmployeeInfo.GetSalary();
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.GetSalary()

_xxx = z => z.EmployeeInfo.Addresses.Select(a => a.Street);
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Addresses.Select(a.Street)

_xxx = z => z.EmployeeInfo.Array[3];
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Array[3]

The implementation:

    static string ExprToString(Expression expr)
{
    switch (expr.NodeType)
    {
        case ExpressionType.Lambda:
            //x => (Something), return only (Something), the Body
            return ExprToString(((LambdaExpression) expr).Body);
        case ExpressionType.Convert:
        case ExpressionType.ConvertChecked:
            //type casts are not important
            return ExprToString(((UnaryExpression) expr).Operand);
        case ExpressionType.Call:
            //method call can be an Indexer (get_Item), 
            var callExpr = (MethodCallExpression) expr;
            if (callExpr.Method.Name == "get_Item")
            {
                //indexer call
                return ExprToString(callExpr.Object) + "[" + string.Join(",", callExpr.Arguments.Select(ExprToString)) + "]";
            }
            else
            {
                //method call
                var arguments = callExpr.Arguments.Select(ExprToString).ToArray();
                string target;
                if (callExpr.Method.IsDefined(typeof (ExtensionAttribute), false))
                {
                    //extension method
                    target = string.Join(".",  arguments[0], callExpr.Method.Name);
                    arguments = arguments.Skip(1).ToArray();
                }
                else if (callExpr.Object == null)
                {
                    //static method
                    target = callExpr.Method.Name;
                }
                else
                {
                    //instance method
                    target = string.Join(".", ExprToString(callExpr.Object), callExpr.Method.Name);
                }
                return target + "(" + string.Join(",", arguments) + ")";
            }
        case ExpressionType.MemberAccess:
            //property or field access
            var memberExpr = (MemberExpression) expr;
            if (memberExpr.Expression.Type.Name.Contains("<>")) //closure type, don't show it.
            {
                return memberExpr.Member.Name;
            }
            else
            {
                return string.Join(".", ExprToString(memberExpr.Expression), memberExpr.Member.Name);
            }
    }
    //by default, show the standard implementation
    return expr.ToString();
}
Sign up to request clarification or add additional context in comments.

6 Comments

Hi, thanks for your response. what is that $"" <-- **$"{target}({string.Join(",", arguments)})";** is this new?
@Bas You are using C# 6.0 things here (the $)
i am using C#4.0 oh God im so outdated
I got it. It is working except for the declared index var _addrName = "Address"; Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses[_addrName];
i am expecting EmployeeInfo.Addresses["Address"] this string Address came from the declared _addrName variable
|

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.