Dynamically generating a class is very helpful for technologies such as AOP,O/R mapping. For Java, it's not a big problem, but for. NET, it's a bit of a hassle (the main problem is that the generation of code needs IL), so it's probably also the reason that Java went a bit further in AOP, O/R mapping.
Trouble is trouble, it can't be, dynamic generation of a simple class is not too difficult.
Suppose you have the following interface:
interface IAnimal
{
void move();
void eat();
}
You want to create a class builder typecreator that you can use in the following ways:
TypeCreator tc=new TypeCreator(typeof(IAnimal));
Type t = tc.build();
IAnimal myAnimal= (IAnimal)Activator.CreateInstance(t);
myAnimal.move();
myAnimal.eat();
First, the discovery that System.Reflection.Emit.TypeBuilder seems to be a ready-made class builder. However, TypeBuilder has neither a practical static method nor an external instantiation. But ModuleBuilder has a definetype () method that can get TypeBuilder, and ModuleBuilder and typerbuilder a virtue that cannot be created directly, Obtained from the AssemblyBuilder DefineDynamicModule () method. Traced, AssemblyBuilder from the AppDomain of DefineDynamicAssembly (). In the end, AppDomain provides a static method: Appdomain.currentdomain. This series is not unreasonable, the type is attached to the module, and the module is attached to the Assembly, and the assembly is AppDomain loaded. The so-called "with, Mao", in order to create the type of "Mao", we have to first put the assembly,module of these "skins" in sequence to construct out:
Using System;
using System.Reflection;
using System.Reflection.Emit;
public class Typecreator
{
private Type TargetType;
///<summary>
///Construction Function
///</summary>
///<param name= "TargetType" > Implemented or inherited type </param>
public Typecreator (Type targettype)
{
this.targettype = TargetType;
}
public Type Build ()
{
//Get current AppDomain
AppDomain currentappdomain = Appdomain.currentdomain;
//system.reflection.assemblyname is used to represent the full name of a assembly
AssemblyName assyname = new AssemblyName ();
//defines a name for the assembly to be created (this ignores the version number, culture, and other information)
assyname.name = "Myassyfor_" + targettype.name;
//Get AssemblyBuilder
AssemblyBuilderAccess has run,save,runandsave three values
AssemblyBuilder assybuilder = currentappdomain.definedynamicassembly (Assyname,assemblybuilderaccess.run);
//Get ModuleBuilder, provide string parameter as the module name, and set up a random
ModuleBuilder Modbuilder = Assybuilder.definedynamicmodule ("Mymodfor_" +targettype.name);
//new type name: Just set a
String newtypename = "Imp_" +targettype.name;
//new type of attribute: class to be created, not interface,abstract class, and public
typeattributes Newtypeattribute = Typeattributes.class | Typeattributes.public;
//Declares the parent type of the new type to be created
Type newtypeparent;
//Declares the interface to be implemented for the new type to be created
type[] newtypeinterfaces;
///whether the base type is an interface for different processing
if (targettype.isinterface)
{
newtypeparent = null;
newtypeinterfaces = new Type[]{targettype};
}
Else
{
newtypeparent = TargetType;
newtypeinterfaces = new Type[0];
}
//Get Type builder
TypeBuilder TypeBuilder = Modbuilder.definetype (newtypename,newtypeattribute,newtypeparent,newtypeinterfaces) ;
//The following will declare the method for the new type: The new type should override the base type, so the virtual method
//Get all the methods of the base type
methodinfo[] targetmethods = Targettype.getmethods ();
//Traversal of each method, for virtual method, obtain its signature, as a new type of method
foreach (MethodInfo targetmethod in Targetmethods)
{
//Only pick out the virtual method
if (targetmethod.isvirtual)
{
//Get the type of each parameter of the method
parameterinfo[] Paraminfo = Targetmethod.getparameters ();
type[] Paramtype = new Type[paraminfo.length];
for (int i=0;i<paraminfo.length;i++)
Paramtype[i] = Paraminfo[i]. ParameterType;
//Incoming method signature, get method builder
MethodBuilder MethodBuilder = Typebuilder.definemethod (targetmethod.name,methodattributes.public|
Methodattributes.virtual,targetmethod.returntype,paramtype);
//Because the concrete class is to be generated, the implementation of the method is essential. And the implementation of the method is generated by emit IL code
//Get IL generator
ILGenerator Ilgen = Methodbuilder.getilgenerator ();
//The following three lines are equivalent to: {Console.writeln ("I ' m" + targetmethod.name + "ing");}
Ilgen.emit (opcodes.ldstr, "I ' m" + targetmethod.name + "ing");
Ilgen.emit (opcodes.call,typeof (Console). GetMethod ("WriteLine", New Type[]{typeof (String)});
Ilgen.emit (Opcodes.ret);
}
}
//really create, and return
return (TypeBuilder.CreateType ());
}
}