Implementation of dynamic class generation via emit in Java

Source: Internet
Author: User
Tags aop emit reflection

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 ());


 }


}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.