ExpressionTreeToString 3.4.71

dotnet add package ExpressionTreeToString --version 3.4.71
NuGet\Install-Package ExpressionTreeToString -Version 3.4.71
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ExpressionTreeToString" Version="3.4.71" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ExpressionTreeToString --version 3.4.71
#r "nuget: ExpressionTreeToString, 3.4.71"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install ExpressionTreeToString as a Cake Addin
#addin nuget:?package=ExpressionTreeToString&version=3.4.71

// Install ExpressionTreeToString as a Cake Tool
#tool nuget:?package=ExpressionTreeToString&version=3.4.71

Expression Tree To String

AppVeyor build status Tests NuGet Status       Test objects: NuGet TestObjects Status

Targets .NET Standard 2.0 and above / Framework 4.5.2 and above

Provides a ToString extension method which returns a string representation of an expression tree (an object inheriting from System.Linq.Expressions.Expression).

Expression<Func<bool>> expr = () => true;

Console.WriteLine(expr.ToString("C#"));
// prints: () => true

Console.WriteLine(expr.ToString("Visual Basic"));
// prints: Function() True

Console.WriteLine(expr.ToString("Factory methods", "C#"));
// prints:
/*
    // using static System.Linq.Expressions.Expression

    Lambda(
        Constant(true)
    )
*/

Console.WriteLine(expr.ToString("Object notation", "C#"));
// prints:
/*
    new Expression<Func<bool>> {
        NodeType = ExpressionType.Lambda,
        Type = typeof(Func<bool>),
        Body = new ConstantExpression {
            Type = typeof(bool),
            Value = true
        },
        ReturnType = typeof(bool)
    }
*/

Console.WriteLine(expr.ToString("Object notation", "Visual Basic"));
// prints:
/*
    New Expression(Of Func(Of Boolean)) With {
        .NodeType = ExpressionType.Lambda,
        .Type = GetType(Func(Of Boolean)),
        .Body = New ConstantExpression With {
            .Type = GetType(Boolean),
            .Value = True
        },
        .ReturnType = GetType(Boolean)
    }
*/

Console.WriteLine(expr.ToString("Textual tree"));
// prints:
/*
    Lambda (Func<bool>)
        Body - Constant (bool) = True
*/

var b = true;
Expression<Func<int>> expr1 = () => b ? 1 : 0;
Console.WriteLine(expr1.ToString("ToString"));
// prints:
/*
    () => IIF(value(_tests.Program+<>c__DisplayClass0_0).b, 1, 0)
*/

Console.WriteLine(expr1.ToString("DebugView"));
// prints:
/*
    .Lambda #Lambda1<System.Func`1[System.Int32]>() {
        .If (
            .Constant<_tests.Program+<>c__DisplayClass0_0>(_tests.Program+<>c__DisplayClass0_0).b
        ) {
            1
        } .Else {
            0
        }
    }
*/

Expression<Func<Person, bool>> filter = p => p => p.LastName == "A" || p.FirstName == "B" || p.DOB == DateTime.MinValue || p.LastName == "C" || p.FirstName == "D";
Console.WriteLine(filter.ToString("Dynamic LINQ", "C#"));
// prints:
/*
    "LastName in (\"A\", \"C\") || FirstName in (\"B\", \"D\") || DOB == DateTime.MinValue"
*/

Features:

  • Multiple writers:

    • Pseudo-code in C# or VB.NET
    • Factory method calls which generate this expression
    • Object notation, using object initializer and collection initializer syntax to describe objects
    • Textual tree, focusing on the properties related to the structure of the tree
    • ToString and DebugView reimplementation
    • Dynamic LINQ equivalent to the expression
  • For C# and VB pseudo-code representations:

    • Extension methods are rendered as instance methods

      Expression<Func<int, int>> expr = x => Enumerable.Range(1, x).Select(y => x * y).Count();
      Console.WriteLine(expr.ToString("C#"));
      // prints: (int x) => Enumerable.Range(1, x).Select((int y) => x * y).Count()
      
    • Closed-over variables are rendered as simple identifiers (instead of member access on the hidden compiler-generated class)

      var i = 7;
      var j = 8;
      Expression<Func<int>> expr = () => i + j;
      Console.WriteLine(expr.ToString("C#"));
      // prints: () => i + j
      
    • Calls to String.Concat and String.Format are mapped to the + operator and string interpolation, respectively (where possible):

      var name = "World";
      Expression<Func<string>> expr = () => string.Format("Hello, {0}!", name);
      Console.WriteLine(expr.ToString("C#"));
      // prints: () => $"Hello, {name}!"
      
    • Unnecessary conversions are not rendered:

      Expression<Func<IEnumerable<char>>> expr = () => (IEnumerable<char>)"abcd";
      Console.WriteLine(expr.ToString("C#"));
      // prints: () => "abcd"
      
    • Comparisons against an enum or char are rendered properly, not as comparison to int-converted value:

      var dow = DayOfWeek.Sunday;
      Expression<Func<bool>> expr = () => DateTime.Today.DayOfWeek == dow;
      
      Console.WriteLine(expr.ToString("Textual tree", "C#"));
      // prints:
      /*
        Lambda (Func<bool>)
            · Body - Equal (bool) = false
                · Left - Convert (int) = 3
                    · Operand - MemberAccess (DayOfWeek) DayOfWeek = DayOfWeek.Wednesday
                        · Expression - MemberAccess (DateTime) DateTime.Today = 30/09/2020 12:00:00 am
                · Right - Convert (int) = 0
                    · Operand - MemberAccess (DayOfWeek) dow = DayOfWeek.Sunday
                        · Expression - Constant (<closure>) = #<closure>      
      */
      
      Console.WriteLine(expr.ToString("C#"));
      // prints: () => DateTime.Today.DayOfWeek == dow
      
  • Each representation (including the ToString and DebugView renderers) can return the start and length of the substring corresponding to any of the paths of the tree's nodes, which can be used to find the substring corresponding to a given node in the tree:

    var s = expr.ToString("C#", out var pathSpans);
    Console.WriteLine(s);
    // prints: (Person p) => p.DOB.DayOfWeek == DayOfWeek.Tuesday
    
    (int start, int length) = pathSpans["Body.Left.Operand"];
    Console.WriteLine(s.Substring(start, length));
    // prints: p.DOB.DayOfWeek
    
  • Type names are rendered using language syntax and keywords, instead of the Type.Name property; e.g. List<string> or List(Of Date) instead of List`1

  • Supports the full range of types in System.Linq.Expressions, including .NET 4 expression types, and DynamicExpression

  • Extensibility -- allows creating custom renderers, or inheriting from existing renderers, to handle your own Expression-derived types

For more information, see the wiki.

Feedback

  • Star the project
  • File an issue
Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net452 is compatible.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (10)

Showing the top 5 NuGet packages that depend on ExpressionTreeToString:

Package Downloads
RaaLabs.Edge The ID prefix of this package has been reserved for one of the owners of this package by NuGet.org.

Package Description

NCPC.Utils

Usefull methods of common use

ExpressionTreeVisualizer.UI

UI pieces for displaying expression trees

PackSite.Library.Modeling.Specifications

Querying specifications

NiuX.Common

csharp common, utils, helpers, tools etc.

GitHub repositories (2)

Showing the top 2 popular GitHub repositories that depend on ExpressionTreeToString:

Repository Stars
yangzhongke/NETBookMaterials
zspitz/ExpressionTreeVisualizer
Debugging visualizer for expression trees
Version Downloads Last updated
3.4.71 136,486 2/25/2022
3.4.70 3,762 12/23/2021
3.4.68 1,031 12/14/2021
3.4.67 280 12/14/2021
3.4.65 22,422 7/14/2021
3.4.64 347 7/14/2021
3.4.63 11,675 7/5/2021
3.4.62 574 6/29/2021
3.4.61 538 6/23/2021
3.4.60 351 6/23/2021
3.3.59 395 6/17/2021
3.3.58 455 6/7/2021
3.3.57 353 6/6/2021
3.3.56 412 5/31/2021
3.2.54 42,197 1/16/2021
3.2.53 6,788 12/6/2020
3.2.52 519 12/5/2020
3.2.51 513 12/5/2020
3.2.50 508 12/5/2020
3.2.49 400 12/5/2020
3.2.48 2,171 10/28/2020
3.1.47 469 10/8/2020
3.1.45 687 9/30/2020
3.1.44 523 9/30/2020
3.1.43 453 9/24/2020
3.1.42 476 9/23/2020
3.0.41 577 9/16/2020
2.2.40 467 9/15/2020
2.2.39 448 9/15/2020
2.2.38 436 9/14/2020
2.2.37 537 8/31/2020
2.2.36 458 8/26/2020
2.1.34 468 8/24/2020
2.1.33 401 8/24/2020
2.0.32 499 8/18/2020
2.0.29 891 8/5/2020
2.0.28 497 7/19/2020
2.0.27 4,033 7/19/2020
2.0.26 546 7/19/2020
2.0.25 446 7/16/2020
2.0.23 528 6/28/2020
2.0.22 549 6/27/2020
2.0.21 533 6/27/2020
2.0.20 5,691 3/29/2020
2.0.19 587 3/29/2020
2.0.15 738 12/18/2019
2.0.14 521 12/18/2019
2.0.13 517 12/18/2019
2.0.12 488 12/18/2019
2.0.11 500 12/18/2019
2.0.10 546 12/16/2019
2.0.4 494 12/15/2019
1.6.2 534 12/15/2019
1.5.67 2,687 8/15/2019
1.5.66 634 8/14/2019
1.5.65 659 8/13/2019
1.4.64 657 8/1/2019
1.4.63 649 7/4/2019
1.4.62 626 7/4/2019
1.4.57 614 6/26/2019
1.3.55 638 6/25/2019
1.3.54 637 6/25/2019
1.3.53 612 6/24/2019
1.3.52 649 6/23/2019
1.3.51 635 6/21/2019
1.3.50 655 6/21/2019
1.3.49 648 6/21/2019
1.3.41 624 6/20/2019
1.3.35 631 6/18/2019
1.3.34 663 5/30/2019
1.3.33 649 5/30/2019
1.2.32 654 5/30/2019
1.2.30 663 5/30/2019
1.2.29 624 5/29/2019
1.2.28 683 5/21/2019
1.2.27 665 5/14/2019
1.2.19 3,245 5/3/2019
1.1.10 683 3/24/2019
1.1.7 676 3/15/2019
1.1.6 648 3/14/2019
1.1.5 631 3/14/2019
1.0.1 746 2/17/2019
1.0.0 748 2/14/2019

Non-statement expression support is complete, escaped string literals, exceptions written into source