表达式 Lambda Func 到 c# 中的字符串

Expression Lambda Func to string in c#

我想获取 lambda Func<> Expression 的字符串表示形式以获取 属性 路径。我有这个例子

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

我期待一个字符串

"EmployeeInfo.Addresses["Address"]"

当我做 _xxx.ToString(); 时,我将只做一些字符串解析,我可以得到上面的结果。

我的问题是什么时候做

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

我得到了一个很长的字符串

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

这是很难想出的 "EmployeeInfo.Addresses["地址"]"

有什么办法可以达到我的目的吗?

TIA

这应该会让你走得更远 - 它很老套,但我认为没有办法解决它:

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]

实施:

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