Expression.ToString()有效吗?

时间:2015-12-06 10:53:06

标签: c# .net lambda linq-expressions

我有一个生成的lambda,但是当我想看它像普通的lambda时,它只是没有显示任何东西。当我致电expr.Body.ToString()时,我得到了以下信息:

{var compareA; ... }

但是DebugView for expression工作正常:

.Lambda #Lambda1<System.Comparison`1[XLinq.Test.Comparers.CustomComparerTest+Test]>(
    XLinq.Test.Comparers.CustomComparerTest+Test $x,
    XLinq.Test.Comparers.CustomComparerTest+Test $y) {
    .Block(System.Int32 $compareA) {
        $compareA = .Call ($x.A).CompareTo($y.A);
        .If ($compareA != 0) {
            .Return #Label1 { $compareA }
        } .Else {
            .Block(System.Int32 $compareB) {
                $compareB = .Call ($x.B).CompareTo($y.B);
                .If ($compareB != 0) {
                    .Return #Label1 { $compareB }
                } .Else {
                    .Block(System.Int32 $compareC) {
                        $compareC = .Call ($x.C).CompareTo($y.C);
                        .If ($compareC != 0) {
                            .Return #Label1 { $compareC }
                        } .Else {
                            .Block(System.Int32 $compareD) {
                                $compareD = .Call ($x.D).CompareTo($y.D);
                                .If ($compareD != 0) {
                                    .Return #Label1 { $compareD }
                                } .Else {
                                    .Default(System.Void)
                                }
                            }
                        }
                    }
                }
            }
        };
        .Label
            0
        .LabelTarget #Label1:
    }
}

为什么我得到这个结果?

1 个答案:

答案 0 :(得分:4)

这是因为Expression.ToString覆盖依赖于内部ExpressionStringBuilder访问者类型,这会产生极为简化的表达式树表示。

由每个Expression派生类型(即[DebuggerTypeProxy(typeof(Expression.BlockExpressionProxy))]上的BlockExpression)定义的自定义调试器代理提供的调试视图提供了更多信息,因为您已经发现,通过公开更详细的DebugViewWriter访问者(也是内部访问者)的输出。

不幸的是,除非您愿意使用反射来获取私有DebugView属性的值(在{{1}中定义),否则您无法在调试方案之外轻松获得该输出})如下:

System.Linq.Expressions.Expression

可生产

Expression<Func<string, int>> expr = str => str.Length;
BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
PropertyInfo debugViewProp = typeof(Expression).GetProperty("DebugView", flags);
MethodInfo debugViewGetter = debugViewProp.GetGetMethod(nonPublic: true);
string debugView = (string)debugViewGetter.Invoke(expr, null);

与往常一样,Reference Source是您最好的朋友:

http://referencesource.microsoft.com/#System.Core/Microsoft/Scripting/Ast/Expression.cs,aa5f054356a8a17d