Monday, June 11, 2007

Runtime Type/Class generator or modifier with System.Reflection.Emit

Hi,
C# gives you so much flexibility to generate runtime type or modify any type at runtime.
Recently i explore runtime type generation or modification.
Hope every body found it interesting.

What i want to do is,
I have a interface actually i have type which is an interface and I want to generate a class implementing that interface.

Original code should be :

//interface
public interface IEcho
{
string Echo(string message);
}
//Implementor
public class EchoProxy : IEcho
{
public string Echo(string message);
}

now I write a method which will take the type of interface as parameter and return the object of dynamic class.


object GetObject(Type interfaceType)
{
AppDomain proxyDomain = Thread.GetDomain();
// Get the domain of the current thread
AssemblyName proxyAssemblyName = new System.Reflection.AssemblyName();
// You must create a runtime assembly for the type, so you need a name for that assembly
// declare assembly name for dynamic types.
proxyAssemblyName.Name = "ProxyAssembly";
// The name of the newly created assembly is ProxyAssembly.
AssemblyBuilder proxyAssemblyBuilder = proxyDomain.DefineDynamicAssembly(proxyAssemblyName, System.Reflection.Emit.AssemblyBuilderAccess.Run);
// Now you have to create assembly builder to build the assembly builder access option here I use just Run
ModuleBuilder proxyModuleBuilder = proxyAssemblyBuilder.DefineDynamicModule("ProxyModule");
// Now I build a module to hold my dynamic type from assembly builder.
TypeBuilder proxyBuilder = proxyModuleBuilder.DefineType("EchoProxy"
);
// And finally I create a type builder from module builder for dynamic type. The name of the new type is EchoProxy.
proxyBuilder.AddInterfaceImplementation(
interfaceType);
// Here I add the interface to the class, now my dynamic type implement the interface
MethodInfo[] methods =
interfaceType.GetMethods();
// Retrive the collection of methods from the interface.
for (int methodIndex = 0; methodIndex <
methods.Length ; methodIndex++)
{
MethodInfo currentMethod = methods[methodIndex];
// Obtain the current method.
Type[] paramType = new Type[realMethod.GetParameters().Length];
// Create an array of type which will passes as parameter.
for (int parameterIndex = 0; parameterIndex <
realMethod.GetParameters().Length; parameterIndex++)
paramType[parameterIndex] = currentMethod.GetParameters()[parameterIndex].ParameterType;
// Assign the type from interface
MethodBuilder proxyMethodBuilder = proxyBuilder.DefineMethod(
currentMethod.Name, currentMethod.Attributes, currentMethod.CallingConvention, currentMethod.ReturnType, paramType);
// Now create a method builder from type builder, with the specific parameter and return type.
// And the most annoying portion of the total work begin here.
// you have to write IL/OpCode here.
ILGenerator codeBlockGenerator = proxyMethodBuilder.GetILGenerator();
// Create a ILGenerator from Method builder
// Which helps you to flush the IL into IL stream.
codeBlockGenerator.Emit(OpCodes.Nop);
// OpCode = NOP
// It is practice to start a method with nop
codeBlockGenerator.EmitWriteLine("This is Proxy");
// OpCode = Print Line
codeBlockGenerator.Emit(OpCodes.Ldarg_0);
// Load the argument into evolution stack
codeBlockGenerator.Emit(OpCodes.Ret);
// Just return
// Return statement always pop last item from evolution stack and return it
}
return System.Activator.CreateInstance(
proxyBuilder.CreateType());
// Create a dynamic type from proxy builder and I create an instance from that with activator
// And return the instance of that type.
}

Now I am ready to use this method
public UseDynamicInstance()
{
IEcho simpleEcho =
GetObject(typeof(IEcho)) as IEcho;
if(
simpleEcho != null)
{
simpleEcho.Echo("Are you Ok");
}
}

Now what I am trying to show is that you can create runtime type and create an instance of it.
I find this helpful to create dynamic proxy Item
Hope you will find it so.
And you must include System.Reflection.Emit for these classes.

No comments:

Post a Comment

Please, no abusive word, no spam.