Generate new Types dynamically at runtime using Reflection Emit


This article explain about how to Generate new Types dynamically at runtime using Reflection Emit with code snippet

Reflection emit supports the dynamic creation of new types at runtime. You can define an assembly to run dynamically, and you can define modules and new types with methods that you can then invoke. Reflection emit allows to just "emit" the IL codes directly. The ILGenerator class is used to generate the IL code dynamically. Here are the steps summarized very briefly:
1. Create an object of AssemblyBuilder; which defines a dynamic assembly
2. Create an object of ModuleBuilder from the dynamic assembly. This object would represent the module
3. Define your Type using the object of ModuleBuilder. You get back a TypeBuilder object.
4. Define the methods you want to have in your new type using the TypeBuilder object. You get back MethodBuilder object(s).
5. Now; from the MethodBuilder object you can get the ILGenerator object; which you can use to write the IL for the method. You can take the help of OpCodes from System.Reflection.Emit to generate the IL; which provides different field level instructions.
6. Finally; you call CreateType( )on the TypeBuilder object to load its Type and return the dynamic assembly you just created to the client.

The example given here; creates a new Type dynamically which implements an example Interface called IFactorial. The IFactorial interface defines only one method: FindFactorial which returns the factorial of the specified integer. Since you are emitting code dynamically it is always good to have the new Type implement a known interface. So that your client code knows which method to invoke: your code talks to the interface, not to the new Type which has been created on the fly. In the example class the step by step procedure to dynamically generate the new Type is explained. Please follow the comment lines.
This is the primary Interface:


public interface IFactorial
{
long FindFactorial();
}

And here is the Reflection Emit demo class:

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

public class ReflectionEmitDemo
{
Assembly assembly;
IFactorial factorial;

public long FindFactorialOntheFly(int number)
{
if (factorial == null)
{
assembly = EmitAssembly(number);
factorial = (IFactorial)assembly.CreateInstance("FactorialFinder");
}
return factorial.FindFactorial();
}

Assembly EmitAssembly(int number)
{
//Create an assembly name
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "FactorialAssembly";
//Create an assembly with one module
AssemblyBuilder newAssembly =
Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder newModule = newAssembly.DefineDynamicModule("Factorial");
//Define a public class in the assembly
TypeBuilder newType = newModule.DefineType("FactorialFinder", TypeAttributes.Public);
//Mark the class as implementing IFactorial interface
newType.AddInterfaceImplementation(typeof(IFactorial));
//Define a method on the new type to call
Type[] paramTypes = new Type[0];
Type returnType = typeof(long);
MethodBuilder newMethod = newType.DefineMethod("FindFactorial", MethodAttributes.Public | MethodAttributes.Virtual,
returnType, paramTypes);
//Get an IL Generator, which will be used to emit the required IL
ILGenerator generator = newMethod.GetILGenerator();

//Emit the IL in lines of the FindFactorial defined above
generator.Emit(OpCodes.Ldc_I8, 1L); //push '1' into the evaluation stack
for (long i = 1L; i <= number; i++)
{
//push the current number into evaluation stack
generator.Emit(OpCodes.Ldc_I8, i);
//muliply the two successive numbers and push into the evaluation stack
generator.Emit(OpCodes.Mul);
}
//return the value;
generator.Emit(OpCodes.Ret);

//Now override the method defination from IFactorial in the FindFactorial class
MethodInfo methodInfo = typeof(IFactorial).GetMethod("FindFactorial");
newType.DefineMethodOverride(newMethod, methodInfo);
newType.CreateType();
return newAssembly;
}
}

Here is an easy test code:

Console.WriteLine("Factorial of {0} is {1}", 5, new ReflectionEmitDemo().FindFactorialOntheFly(5));


Comments

No responses found. Be the first to comment...


  • Do not include your name, "with regards" etc in the comment. Write detailed comment, relevant to the topic.
  • No HTML formatting and links to other web sites are allowed.
  • This is a strictly moderated site. Absolutely no spam allowed.
  • Name:
    Email: