📜 ⬆️ ⬇️

Dynamic code compilation in C #

Using a compiler from C # code is quite simple. But why - this is another question :).

Hello world


Let's write the first simple example. Create a console application and write the following code:
using System;<br> using System.CodeDom.Compiler;<br> using System.Collections. Generic ;<br> using Microsoft.CSharp;<br><br> namespace ConsoleCompiler<br>{<br> internal class Program<br> {<br> private static void Main( string [] args)<br> {<br> // Source code <br> string source =<br> @"<br>namespace Foo<br>{<br> public class Bar<br> {<br> static void Main(string[] args)<br> {<br> Bar.SayHello();<br> }<br><br> public static void SayHello()<br> {<br> System.Console.WriteLine(" "Hello World" ");<br> }<br> }<br>}<br> " ;<br><br> // <br> Dictionary< string , string > providerOptions = new Dictionary< string , string ><br> {<br> { "CompilerVersion" , "v3.5" }<br> };<br> CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);<br><br> CompilerParameters compilerParams = new CompilerParameters<br> {OutputAssembly = "D:\\Foo.EXE" , GenerateExecutable = true };<br><br> // <br> CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, source);<br><br> // <br> Console .WriteLine( "Number of Errors: {0}" , results.Errors.Count);<br> foreach (CompilerError err in results.Errors)<br> {<br> Console .WriteLine( "ERROR {0}" , err.ErrorText);<br> }<br> }<br> }<br>} <br><br> * This source code was highlighted with Source Code Highlighter .

We start and check:
First Sample
The first thing you should pay attention to is the use of two namespaces (namespace):These classes contain the key to the ability to compile. In our example, we specify that we will compile under the .NET Framework 3.5, as well as indicate what we want to get at the output - Foo.exe, with the ability to run this application.

The example is more difficult, we use Linq


Now let's complicate our example, add Linq to the compiled code:
string source = @"<br> using System.Collections.Generic;<br>using System.Linq; <br><br>namespace Foo<br>{<br> public class Bar<br> {<br> static void Main(string[] args)<br> {<br> Bar.SayHello();<br> }<br><br> public static void SayHello()<br> {<br> System.Console.WriteLine(" "Hello World" ");<br> System.Console.WriteLine( string.Join(" "," ", Enumerable.Range(0,10).Select(n=>n.ToString()).ToArray() ) ); <br> }<br> }<br>}" ; <br><br> * This source code was highlighted with Source Code Highlighter .

Added lines are marked in red, if we try to run the previous example with modified compiled code, then we will see compilation errors:
Compiler Error
For the compilation to succeed, you need to add a link to the System.Core.dll assembly in the compilation options.
compilerParams.ReferencedAssemblies.Add( "System.Core.Dll" ); <br><br> * This source code was highlighted with Source Code Highlighter .

And now everything will work:
Linq Sample

We use the created assembly in the code


Now we will try to compile the Foo.dll assembly instead of the executable file, as well as immediately after compilation, download and use the compiled method. We will change the compiled code, we will make it easier:
stringsource = @"<br>using System.Collections.Generic;<br>using System.Linq;<br><br>namespace Foo<br>{<br> public class Bar<br> {<br> public static void SayHello()<br> {<br> System.Console.WriteLine(" "Hello World" ");<br> System.Console.WriteLine( string.Join(" "," ", Enumerable.Range(0,10).Select(n=>n.ToString()).ToArray() ) );<br> }<br> }<br>}" ; <br><br> * This source code was highlighted with Source Code Highlighter .

Change the compiler settings, now we will build the dll file:
const string outputAssembly = "D:\\Foo.dll" ;<br>CompilerParameters compilerParams = new CompilerParameters {OutputAssembly = outputAssembly, GenerateExecutable = false }; <br><br> * This source code was highlighted with Source Code Highlighter .

After compiling and checking errors using Reflection (don't forget to connect the namespace - using System.Reflection) we call the Foo.Bar.SayHello () method compiled dll:
Console .WriteLine( "Try Assembly:" );<br> Assembly assembly = Assembly .LoadFile(outputAssembly);<br>Type type = assembly.GetType( "Foo.Bar" );<br>MethodInfo method = type.GetMethod( "SayHello" );<br>method.Invoke( null , null ); <br><br> * This source code was highlighted with Source Code Highlighter .

Result:
Final Result
The final example can be downloaded from mydrive.live.com .
Information about dynamic compilation and the main examples I took from here: Saveen Reddy's blog - A Walkthrough of Dynamically Compiling C # code (English).
Progg it

')

Source: https://habr.com/ru/post/67431/


All Articles