Generating Executable Code or Class Libraries for Custom Class Snippets (C# Script) at Runtime
This Article provides a code Snippet to illustrate generating executable code (classes) at run time using C# compiler.
This Sample also includes Code to use Reflection to create instance of a class (from specified namespace) and also to call class methods alongwith parameters.
Compiling C# script at runtime
Features covered in this Article are:
1. Runtime compilation of C# code
2. Reflection
Microsoft.CSharp.CSharpCodeProvider class provides feature to compile any C# code that you (our your user) feeds to the application on-the-fly.
Once the code is compiled its members can be accessed with the help of reflection (another features of .Net) and perform any operation like you do with a normal C# class member.
Start with Visual Studio 2010 Console Application and make your main() method as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// Included for C# script compilation at run time
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
namespace HiEverybody
{
class Program
{
static void Main(string[] args)
{
#region MAKING 2 EXECUTION BLOCKS
string block1 =
@"
namespace HiEverybody
{
public class WelcomeClass
{
public void TestMethod(string userMessage)
{
MyLibrary myLibrary = new MyLibrary();
System.Console.WriteLine(""This Code block was compiled because you entered Option : 1"");
myLibrary.MyMethod1(""'"" + userMessage + ""' This message was entered by you"");
myLibrary.MyMethod2(""'Welcome World!' This is System generated message"");
System.Console.ReadKey();
}
}
public class MyLibrary
{
public void MyMethod1(string message)
{
System.Console.WriteLine(""(in MyMethod1) : "" + message);
}
public void MyMethod2(string message)
{
System.Console.WriteLine(""(in MyMethod2) : "" + message);
}
}
}";
string block2 =
@"
namespace HiEverybody
{
public class WelcomeClass
{
public void TestMethod(string userMessage)
{
System.Console.WriteLine(""This Code block was compiled because you entered Option : 2"");
System.Console.WriteLine(""(in TestMethod) : '"" + userMessage + ""' This message was entered by you"");
System.Console.ReadKey();
}
}
}";
#endregion
#region USER INPUT
Console.WriteLine("Enter the option (1 or 2):");
String option = Console.ReadLine();
if (null == option)
{
Console.WriteLine("!! BLANK !! Wrong Option?");
Console.ReadKey();
return;
}
if (!(option == "1" || option == "2"))
{
Console.WriteLine("!! OTHER THEN 1 and 2 !! Wrong Option?");
Console.ReadKey();
return;
}
#endregion
#region C# COMPILER - Perform runtime compilation
// setting the compiler version
Dictionary<string, string> providerOptions = new Dictionary<string, string> { { "CompilerVersion", "v3.5" } };
// getting the C# compiler provider
CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);
// setting compilation parameters
CompilerParameters compilerParams = new CompilerParameters
{
// output will be generated in memory
GenerateInMemory = true,
// output will be of type "executable"
GenerateExecutable = false
// there are also other parameters for different types of initial settings
};
// start with a CompilerResults reference as null (will be instentiated as per the option selected)
CompilerResults compilerResults = null;
// compiling as per the option
object[] myParameters = null;
// compile as per requirement
if (option == "1")
{
compilerResults = provider.CompileAssemblyFromSource(compilerParams, block1);
myParameters = new object[] { "Its too cold today!!..." }; // this is your parameter for method
}
if (option == "2")
{
compilerResults = provider.CompileAssemblyFromSource(compilerParams, block2);
myParameters = new object[] { "Its too hot today!!..." }; // this is your parameter for method
}
// see if any error generated during compilation
if (compilerResults.Errors.Count != 0)
throw new Exception("Run time compilation Failed!");
#endregion
// we are here that means Runtime compilation of C# code was successful
#region REFLECTION - Executing desired method
// create class object
var myClassObject = compilerResults.CompiledAssembly.CreateInstance("HiEverybody.WelcomeClass");
// retrieve the required method name to execute
MethodInfo methodInfo = myClassObject.GetType().GetMethod("TestMethod");
// invoking the desired method
methodInfo.Invoke(myClassObject, myParameters);
#endregion
}
}
}
Once you are done with code you can test it with F5 (Run).
Hope this Code shippet would help some of the developers writing dynamic codes and compiling them as per runtime requirement.
Thanks
great!!!