Miscellaneous Statements
WriteLine Expression
WriteLineExpression can be used to write line of the text in dynamically generated code. This expression supports several outputs for the text:
Additionally, Code Generator has static methods WriteLine, WriteError and DebugMessage that allow to place this expression as statement into lexical scope.
using System;
using static DotNext.Metaprogramming.CodeGenerator;
var println = Lambda<Action<string>>(fun =>
{
WriteLine(fun[0]);
});
Assertion
Checks for a condition; if the condition is false, outputs messages and displays a message box that shows the call stack. This statement is available as static method Assert from Code Generator only.
The statement is relevant in DEBUG configuration only. In any other configurations, Assert method is ignored.
using DotNext.Linq.Expressions;
using System;
using static DotNext.Metaprogramming.CodeGenerator;
var println = Lambda<Action<string>>(fun =>
{
Assert(fun.IsNotNull(), "Argument is null");
WriteLine(fun[0]);
});
Breakpoint
Signals a breakpoint to an attached debugger. This statement is available as static method Breakpoint from Code Generator only.
The statement is relevant in DEBUG configuration only. In any other configurations, Breakpoint method is ignored.
using DotNext.Linq.Expressions;
using System;
using static DotNext.Metaprogramming.CodeGenerator;
var println = Lambda<Action<string>>(fun =>
{
Breakpoint();
WriteLine(fun[0]);
});
Fragment
Regardless for rich set of helper methods for generating statements and expressions the code written for dynamic code generation may hard to read by developers. It reasonable to simplify construction of compound expressions or statements somehow. C# programming language supports creation of expression tree from single-line expression. This feature is utilized by Metaprogramming library and called expression fragment. The fragment is a body of lambda expression with parameters replaced by actual expressions from the context. It can be embedded as statement inside of multi-line lambda expression.
The following example demonstrates how to generate expression fragment:
using DotNext.Linq.Expressions;
using System;
var fragment = ExpressionBuilder.Fragment<Func<int, int, int>>((x, y) => Math.Max(x, y), 10, 20);
//fragment is MethodCallExpression with two arguments: constant values 10 and 20 of type int
Static method Embed from Code Generator can be used to embed the expression fragment as statement into lexical scope of the multi-line lambda expression:
using System;
using static DotNext.Metaprogramming.CodeGenerator;
var greeting = Lambda<Action<string>>(fun =>
{
Embed<Action<string>>(str => Console.WriteLine("Hello, {0}", str), fun[0]);
});
// the generated code is
new Action<string>(str => Console.WriteLine("Hello, {0}", str)));
Statement
Migration of third-party code from plain Expression Trees to .NEXT Metaprogramming can be challenging due to differences in programming model. The code based on Expression class implements construction of expression trees. The code based on CodeGenerator class implements natural flow of the code: each call of static method represents a single statement. CodeGenerator.Statement static method bridges the gap between two programming model and simplifies code migration:
using System;
using static DotNext.Metaprogramming.CodeGenerator;
var greeting = Lambda<Func<int, int, int>>(fun =>
{
Statement(fun[0] + fun[1]);
});
// the generated code is
new Func<int, int, int>((x, y) => x + y);