将Lambda Func表达为c#

时间:2016-02-09 06:37:15

标签: c#-4.0 lambda expression func

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

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)"

很难操纵起来 &#34; EmployeeInfo.Addresses [&#34;地址&#34;]&#34;

有没有办法达到我的目的?

TIA

1 个答案:

答案 0 :(得分:3)

这应该会让你走得很远 - 这非常hacky但是我认为没有办法解决它:

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