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