28
Mar
0

.Net – Compile C# at runtime|.Net compiler du C# a l’execution

I do not remember where I found this code, but it is very interesting :
you can compile C# in an assembly and then use it as you like.

Voici du code qui permet de compiler du C# a l’execution. L’assembly est gardé en mémoire (mais pourrait etre mis dans un fichier) et est directement utilisable.

What I do

I compile C# but in my code I am using it directly in a method (a constructor). In the real situation I used it in another way, but it was in my job so I cannot explain here what I did.
Anyway, everyone can use it as he likes.

Ce que je fais

Je compile du C# et j’instancie un objet. En réalité je l’utilise pour autre chose (mais c’est dans mon travail alors je le garde pour moi ^^).
Mais chacun peut en faire ce qu’il veut!


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Collections;
using System.Text;

/// <summary>
/// CSharpCompiler
/// </summary>
public class CSharpCompiler
{
 // Compilation errors
 private StringBuilder errors = new StringBuilder();
 public string Errors
 {
 get
 {
 return "Error in the compilation :\n" + errors.ToString();
 }
 }

 public CSharpCompiler(){}

 private string AddClass(string source)
 {
 return "using System;" +
 "using System.Collections.Generic;" +
 "using System.Text;" +
 "public class MySpecialClass" +
 "{" +
 "public MySpecialClass()" +
 "{" +
 source +
 "}" +
 "}";
 }

 public Object Run(string source)
 {
 // Clean error
 errors.Length = 0;

 // Compile
 Assembly assembly = CreateAssembly(AddClass(source));
 if (assembly == null) return null;

 Object obj = assembly.CreateInstance("MySpecialClass");
 return obj;
 }

 private Assembly CreateAssembly(string sourceInClass)
 {

 //On crée une class pour compiler le C#
 CodeDomProvider codeProvider = new CSharpCodeProvider();

 // On devait precedement crée un compilateur
 ///Depreciated ICodeCompiler compiler = codeProvider.CreateCompiler();

 //parametres du compilateur
 CompilerParameters compilerParams = new CompilerParameters();
 compilerParams.CompilerOptions = "/target:library"; // you can add /optimize
 compilerParams.GenerateExecutable = false;
 compilerParams.GenerateInMemory = true;
 compilerParams.IncludeDebugInformation = false;

 //references
 compilerParams.ReferencedAssemblies.Add("mscorlib.dll");
 compilerParams.ReferencedAssemblies.Add("System.dll");
 compilerParams.ReferencedAssemblies.Add("System.Data.dll");
 compilerParams.ReferencedAssemblies.Add("System.Xml.dll");
 compilerParams.ReferencedAssemblies.Add("System.Windows.Forms.dll");

 // On compile
 // depreciated compiler.CompileAssemblyFromSource(
 CompilerResults results = codeProvider.CompileAssemblyFromSource(
 compilerParams,
 sourceInClass);

 // On garde les erreurs
 if (results.Errors.Count > 0)
 {
 foreach (CompilerError error in results.Errors)
 {
 errors.AppendLine("Error : " + error.ErrorText);
 }

 return null;
 }

 // recupere l'assembly
 Assembly generatedAssembly = results.CompiledAssembly;

 // retourne l'assembly
 return generatedAssembly;
 }

 //
 // Imagine we want to call Main function, so use this method.
 //
 // invoke the entry method
 // this method code is mainly from jconwell,
 // see http://www.codeproject.com/dotnet/DotNetScript.asp
 /*
 private void CallEntry(Assembly assembly, string entryPoint)
 {
 try
 {
 //Use reflection to call the static Main function
 Module[] mods = assembly.GetModules(false);
 Type[] types = mods[0].GetTypes();

 foreach (Type type in types)
 {
 MethodInfo mi = type.GetMethod(entryPoint,
 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
 if (mi != null)
 {
 if (mi.GetParameters().Length == 1)
 {
 if (mi.GetParameters()[0].ParameterType.IsArray)
 {
 string[] par = new string[1]; // if Main has string [] arguments
 mi.Invoke(null, par);
 }
 }
 else
 {
 mi.Invoke(null, null);
 }
 return;
 }

 }

 errors.AppendLine("Impossible d'acceder au point d'entre : " + entryPoint);
 }
 catch (Exception ex)
 {
 errors.AppendLine("Erreur : " + ex.Message);
 }
 }
 */
}

You can imagine what you want and Wow I really like this powerful capacity in .Net

But here is how is use it :

Vous pouvez imaginer comme c’est puissant et toutes les possibilités d’utiliser du .Net pendant l’execution.

Voici la fin :


static void Main(string[] args)
 {
 CSharpCompiler csc = new CSharpCompiler();
 // The code to compile
 Object p = csc.Run("Console.WriteLine(\"Hello\");");
 if (p == null) Console.WriteLine(csc.Errors);
 }
Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.

Comments are closed.

Celadon theme by the Themes Boutique