X
logo
Master your Data
7 December 2009

Sample: Dynamically Creating Code at Runtime and Calling from your Program

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();
    }
  }
}
Related Blog Posts