This is a small sample that shows how you can build code at runtime and generate an assembly to execute code which could be defined in a database or something. This example shows how to dynamically create a class that add the values of 2 numbers via the expression =Convert.ToInt32(a) + Convert.ToInt32(b).
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Text;
using Microsoft.CSharp;
namespace ExpressionTest
{ class Program
{ static void Main(string[] args)
{ List<KeyValuePair<string, string>> properties = new List<KeyValuePair<string, string>>();
properties.Add(new KeyValuePair<string, string>("a", "1")); properties.Add(new KeyValuePair<string, string>("b", "200"));
string expression = "=Convert.ToInt32(a) + Convert.ToInt32(b)";
string className = "Expression1";
string methodName = "GetSum";
string namespaceName = "ExpressionTest";
//Create a Class
StringBuilder _class = new StringBuilder();
//Start Usings
_class.Append("using System;\r\n");
//Start Namespace
_class.AppendFormat("namespace {0} {{\r\n", namespaceName); //Start Class
_class.AppendFormat("public class {0} {{\r\n", className); //Start Properties
foreach (KeyValuePair<string, string> p in properties)
{ _class.AppendFormat("public string {0};\r\n", p.Key); }
//Start Constructor
_class.AppendFormat("public {0} () {{\r\n", className); foreach (KeyValuePair<string, string> p in properties)
{ _class.AppendFormat("{0}=\"{1}\";\r\n", p.Key, p.Value); }
//End Constructor
_class.Append("}\r\n");
//Start Expression
_class.AppendFormat("public string {0}() {{\r\n", methodName);
if (expression.StartsWith("=")) { _class.AppendFormat("return Convert.ToString({0});\r\n", expression.Substring(1)); }
//End Expression
_class.Append("}\r\n");
//End Class
_class.Append("}\r\n"); //End Namespace
_class.Append("}\r\n");
//Compile the Class
CompilerParameters options = new CompilerParameters();
options.GenerateInMemory = true;
options.GenerateExecutable = false;
foreach (AssemblyName assembly in typeof(Program).Assembly.GetReferencedAssemblies())
{ options.ReferencedAssemblies.Add(string.Format("{0}.dll", assembly.Name)); }
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerResults results = provider.CompileAssemblyFromSource(options, _class.ToString());
if (!results.Errors.HasErrors)
{ //Invoke the Expression Method
Type t = results.CompiledAssembly.GetType(string.Format("{0}.{1}", namespaceName, className));
object instance = t.InvokeMember(t.Name,
BindingFlags.CreateInstance |
BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.Public, null, null, null, CultureInfo.CurrentCulture);
if (instance != null)
{ string result = (string)t.InvokeMember(methodName,
BindingFlags.InvokeMethod |
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic, null, instance, null, CultureInfo.CurrentCulture);
Console.WriteLine("{0}{1}", result, expression); }
}
Console.ReadLine();
}
}
}