Compile and run code created on the fly from a string or file.
Compiler c = new Compiler(); StreamReader reader = new StreamReader(/*Path to my source file, optional*/); string compilationsource = reader.ReadToEnd(); //read from file or create on-the-fly CodeContainer result = new CodeContainer(); result.CompiledAssembly = c.Compile(compilationsource); result.SourceCode = compilationsource; result.Execute("MyMethod", new object[] { MyClass }); //Send in any parameters you need
A lot more functionality than presented above is possible. To make this possible, you’ll need the following Compiler class
using System; using System.Data; using System.Configuration; using System.Collections; using System.Collections.Generic; using System.CodeDom.Compiler; using Microsoft.CSharp; using System.Text; using System.Reflection; using System.Diagnostics; using System.Security.Policy; using System.IO; using System.Web; namespace MyNamespace { /// /// Summary description for Compiler /// public class Compiler { #region Properties private CompilerErrorCollection compilerErrors = null; public CompilerErrorCollection Errors { get { return compilerErrors; } } private List assemblyReferences = new List(); public List AssemblyReferences { get { return assemblyReferences; } set { assemblyReferences = value; } } #endregion #region Constructor public Compiler() { compilerErrors = new CompilerErrorCollection(); } #endregion #region Compile public System.Reflection.Assembly Compile(string sourceCode) { CodeDomProvider provider = CodeDomProvider.CreateProvider("csharp"); CompilerParameters parameters = new CompilerParameters(); CompilerResults results = null; StringBuilder sb = new StringBuilder(); try { parameters.OutputAssembly = "Compiler"; parameters.ReferencedAssemblies.Add("system.dll"); parameters.ReferencedAssemblies.Add("mscorlib.dll"); parameters.ReferencedAssemblies.Add("system.xml.dll"); parameters.ReferencedAssemblies.Add("system.data.dll"); parameters.ReferencedAssemblies.Add("system.web.dll"); parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll"); parameters.ReferencedAssemblies.Add("DbLib.dll"); foreach (string reference in AssemblyReferences) parameters.ReferencedAssemblies.Add(reference); parameters.CompilerOptions = "/t:library"; parameters.GenerateInMemory = true; parameters.GenerateExecutable = false; parameters.IncludeDebugInformation = false; sb.Append(sourceCode); results = provider.CompileAssemblyFromSource(parameters, sb.ToString()); if (results.Errors.Count != 0) { compilerErrors = results.Errors; throw new Exception("Code compilation errors occurred."); } else { return results.CompiledAssembly; } } catch (Exception) { throw; } } #endregion } /// /// code container /// public class CodeContainer { #region Properties public static List CodeContainers = new List(); private string sourceCode; public string SourceCode { get { return sourceCode; } set { sourceCode = value; } } private string uniqueKey; public string UniqueKey { get { uniqueKey = uniqueKey ?? Guid.NewGuid().ToString(); return uniqueKey; } set { uniqueKey = value; } } private string nameSpace; public string NameSpace { get { if (nameSpace == null && SourceCode != null) nameSpace = util.FirstMatch(SourceCode, @"namespaces+(w+)s?"); return nameSpace; } set { nameSpace = value; } } private string className; public string ClassName { get { if (className == null && SourceCode != null) className = util.FirstMatch(SourceCode, @"classs+(w+)s?"); return className; } set { className = value; } } private System.Reflection.Assembly compiledAssembly = null; public System.Reflection.Assembly CompiledAssembly { get { return compiledAssembly; } set { compiledAssembly = value; } } private List assemblyReferences = new List(); public List AssemblyReferences { get { return assemblyReferences; } set { assemblyReferences = value; } } private CompilerErrorCollection compilerErrors = null; public CompilerErrorCollection Errors { get { return compilerErrors; } } #endregion #region Methods public CodeContainer AddAssemblyReference(string path) { AssemblyReferences.Add(path); return this; } #endregion #region Execute /// /// This method will execute the desired classname.method with /// the parameters passed in and return an object. /// public object Execute(string methodName, object[] parameters) { if (CompiledAssembly == null) Update(); //compile source return Execute(this, methodName, parameters); } public object Execute(CodeContainer codeContainer, string methodName, object[] parameters) { if (codeContainer.CompiledAssembly == null) codeContainer.Update(); object assemblyInstance = null; MethodInfo methodInformation = null; Type type = null; string qualifiedClassName = ""; try { qualifiedClassName += codeContainer.NameSpace + "."; qualifiedClassName += codeContainer.ClassName; assemblyInstance = codeContainer.CompiledAssembly.CreateInstance( qualifiedClassName, false ); type = assemblyInstance.GetType(); methodInformation = type.GetMethod(methodName); return methodInformation.Invoke(assemblyInstance, parameters); } catch (Exception) { throw; } } #endregion #region Update public void Update() { CodeContainer.Update(this); } /// /// Manages the static List CodeContainers. /// Compare this code with that which is set in /// our static List by the UniqueKey. /// If not found, compile and add. /// If found but source code is different, delete, compile, and add. /// If found and source code is the same, grab reference to /// previously compiled assembly. /// The codeContainer passed in will always have its .CompiledAssembly /// property populated after this method (Update) is called. /// public static void Update(CodeContainer codeContainer) { CodeContainer existingCode = null; Compiler compiler = null; System.Reflection.Assembly assembly = null; try { existingCode = GetCodeContainer(codeContainer.UniqueKey); if (existingCode != null) { if (existingCode.SourceCode != codeContainer.SourceCode) { Delete(existingCode); existingCode = null; } } if (existingCode == null) { compiler = new Compiler(); compiler.AssemblyReferences = codeContainer.AssemblyReferences; assembly = compiler.Compile(codeContainer.SourceCode); codeContainer.CompiledAssembly = assembly; CodeContainers.Add(codeContainer); return; } codeContainer.ClassName = existingCode.ClassName; codeContainer.NameSpace = existingCode.NameSpace; codeContainer.CompiledAssembly = existingCode.CompiledAssembly; } catch (Exception) { if (compiler != null) codeContainer.compilerErrors = compiler.Errors; throw; } } #endregion #region Delete /// /// Remove this code container object from our static List. /// public static void Delete(CodeContainer code) { try { code.CompiledAssembly = null; CodeContainers.Remove(code); } catch (Exception) { throw; } } #endregion #region Get Code Container /// /// Get a reference to the static List CodeContainer object /// via its UniqueKey property. /// public static CodeContainer GetCodeContainer(string uniqueKey) { try { return CodeContainers.Find(delegate(CodeContainer record) { return int.Equals(record.UniqueKey, uniqueKey); }); } catch (Exception) { throw; } } #endregion } }
Quick Links
Legal Stuff