【问题标题】:Expression Lambda Func to string in c#表达式 Lambda Func 到 c# 中的字符串
【发布时间】:2016-02-09 06:37:15
【问题描述】:

我想获取 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["Address"]"

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

TIA

【问题讨论】:

    标签: c#-4.0 lambda expression func


    【解决方案1】:

    这应该会让你走得很远 - 它非常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();
    }
    

    【讨论】:

    • 您好,感谢您的回复。那是什么 $""
    • @Bas 你在这里使用 C# 6.0 的东西($
    • 我正在使用 C#4.0 哦,天哪,我已经过时了
    • 我明白了。它正在工作,除了声明的索引 var _addrName = "Address";表达式> _xxx = e => e.EmployeeInfo.Addresses[_addrName];
    • 我期待 EmployeeInfo.Addresses["Address"] 这个字符串地址来自声明的 _addrName 变量
    猜你喜欢
    • 1970-01-01
    • 2016-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 2016-07-14
    • 2015-12-03
    相关资源
    最近更新 更多