Class CodeBuilder
Helper functions for creating and loading dynamic code
Inheritance
Inherited Members
Namespace: LemonEdge.Utils
Assembly: Utils.dll
Syntax
public static class CodeBuilder
Remarks
See https://msdn.microsoft.com/en-us/magazine/mt808499.aspx
For example to load code dynamically:
private static (Assembly, byte[]) LoadCode(string dllName, string code)
{
var syntax = CodeBuilder.ParseSyntaxTree(code);
using (var m = new MemoryStream())
{
var compiled = CodeBuilder.Compile(dllName, m, syntax);
if (compiled.Success)
{
var bytes = m.ToArray();
var assem = CodeBuilder.LoadGeneratedAssembly(bytes);
return (assem, bytes);
}
else throw new Exception("Unable to generate code");
}
}
Properties
GetStandardExecutableReferences
Returns all
Declaration
public static IEnumerable<PortableExecutableReference> GetStandardExecutableReferences { get; }
Property Value
Type | Description |
---|---|
System.Collections.Generic.IEnumerable<PortableExecutableReference> |
Methods
AddOrUpdateMemoryType(Assembly, Byte[])
Adds a single dynamic memory type assembly to always be included.
Declaration
public static void AddOrUpdateMemoryType(Assembly assem, byte[] data)
Parameters
Type | Name | Description |
---|---|---|
System.Reflection.Assembly | assem | The assembly to ensure we are including a |
System.Byte[] | data |
Compile(String, Stream, SyntaxTree)
Compiles the given syntax tree into an assembly in the specified dllStream
with the specified fileName
Declaration
public static EmitResult Compile(string fileName, Stream dllStream, SyntaxTree tree)
Parameters
Type | Name | Description |
---|---|---|
System.String | fileName | The name to give the generated assembly |
System.IO.Stream | dllStream | The stream to compile the dll into |
SyntaxTree | tree | The syntax tree of the code to compile into a dll |
Returns
Type | Description |
---|---|
EmitResult | THe result of the compilation of the dll, including any compile errors, warnings, etc |
EnsureHasType(Assembly)
Ensures the list of executable references include the specified assem
assembly
Declaration
public static Task EnsureHasType(Assembly assem)
Parameters
Type | Name | Description |
---|---|---|
System.Reflection.Assembly | assem | The assembly to ensure we are including a |
Returns
Type | Description |
---|---|
System.Threading.Tasks.Task | A task for loading the specified assembly reference if SetAssemblyReferenceGenerator(Func<Assembly, Task<PortableExecutableReference>>) has been used. |
LoadGeneratedAssembly(Byte[])
Loads the generated assembly into the current app domain
Declaration
public static Assembly LoadGeneratedAssembly(byte[] image)
Parameters
Type | Name | Description |
---|---|---|
System.Byte[] | image | The byte array image of the generated assembly |
Returns
Type | Description |
---|---|
System.Reflection.Assembly | The assembly loaded into the current app domain |
LoadStandardExecutableReferences(Assembly[], IEnumerable<Byte[]>)
When generating dynamic dlls, and compiling code, it will often make reference to libraries within LemonEdge itself such as this Utils assembly, and the API.
As such this is used to load
You shouldn't need to use this, LemonEdge does itself to ensure all relevant AddIn and assemblies can be referenced in custom code
Declaration
public static Task LoadStandardExecutableReferences(Assembly[] assems, IEnumerable<byte[]> customAssemblies)
Parameters
Type | Name | Description |
---|---|---|
System.Reflection.Assembly[] | assems | The list of assemblies we want to generate |
System.Collections.Generic.IEnumerable<System.Byte[]> | customAssemblies | Any list of custom assemblies in their byte array form that we also want to be referenceable |
Returns
Type | Description |
---|---|
System.Threading.Tasks.Task | A task for completing the method - only used if the SetAssemblyReferenceGenerator(Func<Assembly, Task<PortableExecutableReference>>) has been used to provide a custom mechanism of creating the classes |
ParseScriptSyntaxTree(String)
Returns a syntax tree for the given custom c# code configured to accept the code in the format of a script. i.e. doesnt need class declarations, can just have top level code
Declaration
public static SyntaxTree ParseScriptSyntaxTree(string code)
Parameters
Type | Name | Description |
---|---|---|
System.String | code | The code to parse and return a syntax tree for |
Returns
Type | Description |
---|---|
SyntaxTree | A syntax tree for the given custom c# code |
ParseSyntaxTree(String)
Returns a syntax tree for the given custom c# code
Declaration
public static SyntaxTree ParseSyntaxTree(string code)
Parameters
Type | Name | Description |
---|---|---|
System.String | code | The code to parse and return a syntax tree for |
Returns
Type | Description |
---|---|
SyntaxTree | A syntax tree for the given custom c# code |
SetAssemblyReferenceGenerator(Func<Assembly, Task<PortableExecutableReference>>)
Normally we can generate a
However in certain enviroments, such as Blazor, we dont have the assemblies location so we need to download it from an http stream.
This method allows us to override the default generation of a
Declaration
public static void SetAssemblyReferenceGenerator(Func<Assembly, Task<PortableExecutableReference>> getRef)
Parameters
Type | Name | Description |
---|---|---|
System.Func<System.Reflection.Assembly, System.Threading.Tasks.Task<PortableExecutableReference>> | getRef | A function that given an assembly will return a task that can generate a |