joi, 10 decembrie 2009

[C#] Dynamically Generating an Assembly in Memory and using it

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using Microsoft.CSharp;

namespace GeorgeNamespace
{
public class Program
{
static void Main()
{

#region Dynamically Generating an Assembly in Memory
CodeCompileUnit _myProgram = new CodeCompileUnit();//create a program
CodeNamespace _ns = new CodeNamespace("MyNameSpace");//create a namespace
_ns.Imports.Add(new CodeNamespaceImport("System"));//<=> using System;
_myProgram.Namespaces.Add(_ns);//add namespace to program

CodeTypeDeclaration _myClass = new CodeTypeDeclaration("MyClass");//create class
_ns.Types.Add(_myClass);//add class to namespace

CodeEntryPointMethod _entryPointMethod = new CodeEntryPointMethod();//create an entry point method

_entryPointMethod.ReturnType = new CodeTypeReference(typeof(void));//set returned type

//Add Code to method
CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("System.Console"), "WriteLine",
new CodePrimitiveExpression("Hello, World!"));

CodeMethodInvokeExpression cs2 = new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("System.Console"), "WriteLine",
new CodePrimitiveExpression("Press ENTER to finish!"));

CodeMethodInvokeExpression cs3 = new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression("System.Console"), "ReadLine");

_entryPointMethod.Statements.Add(cs1);
_entryPointMethod.Statements.Add(cs2);
_entryPointMethod.Statements.Add(cs3);

_myClass.Members.Add(_entryPointMethod);//add entry method to class

CSharpCodeProvider _codeProvider = new CSharpCodeProvider();//create an instance of code generator/compiler
CompilerParameters _params = new CompilerParameters(null, "MyDynamicProgram", true);//set assemply name
_params.GenerateExecutable = true;//create an .exe

CompilerResults _results = _codeProvider.CompileAssemblyFromDom(_params, _myProgram); //compile the assembly

if (_results.Errors.Count > 0)//check for errors
{
foreach (CompilerError _ce in _results.Errors)
{
Console.WriteLine(string.Format("{0} : {1}", _ce.ErrorNumber, _ce.ErrorText));
}
}


//First sample of usage: generate a type on the fly/create a method and invoke it
if (_results.Errors.Count == 0 && _results.CompiledAssembly != null)
{
Type _objType = _results.CompiledAssembly.GetType( "MyNameSpace.MyClass" );
try
{
if (_objType != null)
{
MethodInfo _mi = _objType.GetMethod("Main");
_mi.Invoke(_objType, new object[] { });
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}

//Second Sample: use AppDomain to load the assembly and to load it.
//AppDomain _appDomain = AppDomain.CreateDomain("MyNewAppDomain");
//_appDomain.ExecuteAssembly(_results.PathToAssembly);
#endregion

#region Dynamic method
ClassSample _sampleDynamicMethod = new ClassSample();
_sampleDynamicMethod.InvokeDynamicMethod();
#endregion

Console.ReadLine();
}
}

public class ClassSample
{
public delegate void MyDelegate();
public void InvokeDynamicMethod()
{
DynamicMethod _dynamicMethod = new DynamicMethod("TempMethod" + Guid.NewGuid(), null, null);
ILGenerator _il = _dynamicMethod.GetILGenerator();

_il.Emit(OpCodes.Ldstr, "Hello, World! From George!");
MethodInfo _methodWriteLine = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
_il.Emit(OpCodes.Call, _methodWriteLine);
_il.Emit(OpCodes.Ret);

//First way of calling the method
_dynamicMethod.Invoke(null, null);

//Second way of calling the method
MyDelegate _myDelegate = (MyDelegate)_dynamicMethod.CreateDelegate(typeof(MyDelegate));
_myDelegate();
}
}
}

Niciun comentariu:

Trimiteți un comentariu