Home

Awesome

ExpressionToCode

ExpressionToCode generates valid, readable C# from an Expression Tree. (nuget: ExpressionToCodeLib)

An example:

  ExpressionToCode.ToCode(
    () => new[] { 1.0, 2.01, 3.5 }.SequenceEqual(new[] { 1.0, 2.01, 3.5 })
  )
== "() => new[] { 1.0, 2.01, 3.5 }.SequenceEqual(new[] { 1.0, 2.01, 3.5 })"

ExpressionToCode also provides something like Groovy's Power Assert which includes the code of the failing assertion's expression and the values of its subexpressions. This functionality is particularly useful in a unit testing framework such as NUnit or xUnit.NET. When you execute the following (failing) assertion:

PAssert.That(()=>Enumerable.Range(0,1000).ToDictionary(i=>"n"+i)["n3"].ToString()==(3.5).ToString());

The assertion fails with the following message:

assertion failed

Enumerable.Range(0, 1000).ToDictionary(i => "n" + i)["n3"].ToString(CultureInfo.InvariantCulture) == 3.5.ToString(CultureInfo.InvariantCulture)
   →   false (caused assertion failure)

Enumerable.Range(0, 1000).ToDictionary(i => "n" + i)["n3"].ToString(CultureInfo.InvariantCulture)
     →   "3"

Enumerable.Range(0, 1000).ToDictionary(i => "n" + i)["n3"]
     →   3

Enumerable.Range(0, 1000).ToDictionary(i => "n" + i)
     →   new Dictionary<string, int> {
              ["n0"] = 0,
              ["n1"] = 1,
              ["n2"] = 2,
              ["n3"] = 3,
              ["n4"] = 4,
              ["n5"] = 5,
              ["n6"] = 6,
              ["n7"] = 7,
              ["n8"] = 8,
              ["n9"] = 9,
              ["n10"] = 10,
              ["n11"] = 11,
              ["n12"] = 12,
              ["n13"] = 13,
              ["n14"] = 14,
              ["n15"] = 15,
              ["n16"] = 16,
              ["n17"] = 17,
              ["n18"] = 18,
              ["n19"] = 19,
              ["n20"] = 20,
              ["n21"] = 21,
              ["n22"] = 22,
              ["n23"] = 23,
              ["n24"] = 24,
              ["n25"] = 25,
              ["n26"] = 26,
              ["n27"] = 27,
              ["n28"] = 28,
              ["n29"] = 29,
              ...
          }

Enumerable.Range(0, 1000)
     →   { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, ... }

3.5.ToString(CultureInfo.InvariantCulture)
     →   "3.5"

ExpressionToCode's output is configurable in various ways. For expressions with small values, a values-on-stalks rendering might instead be used:

var a = 2;
var b = 5;
ExpressionToCodeConfiguration.DefaultAssertionConfiguration.WithAnnotator(CodeAnnotators.ValuesOnStalksCodeAnnotator)
    .Assert(() => Math.Max(a, b) > new[] { 3, 8, 13, 4 }.Average() );
Math.Max(a, b) > new[] { 3, 8, 13, 4 }.Average()  :  assertion failed
      │  │  │       │                     │
      │  │  │       │                     7.0
      │  │  │       new[] { 3, 8, 13, 4 }
      │  │  5
      │  2
      5

Note that the default configuration for asserts (i.e. PAssert.That) limits the length of sequences and strings; the default configuration of code-generation does not.

ExpressionToCode was inspired by Power Assert.NET. It differs from PowerAssert.NET by supporting a larger portion of the lambda syntax and that the generated C# is more frequently valid; the aim is to generate valid C# for all expression trees created from lambda's. Currently supported:

Expression tree support

Not implemented (yet?):

ExpressionToCode API

All classes live in the ExpressionToCodeLib namespace.

These are:

Two public helper classes exist:

A complete listing of the public api is here

Supported platforms


Requires .NET 4.5.2 or .net standard 1.6 (previous versions support older platforms)


If you have any questions, you can contact me via github or mail eamon at nerbonne dot org.

See the documentation above, then download from or import using NuGet, or just checkout the source (license: Apache 2.0 or the MIT license, at your option)!