当前位置:七道奇文章资讯编程技术Java编程
日期:2011-03-22 16:15:00  来源:本站整理

Java中通过Emit实现动态类生成[Java编程]

赞助商链接



  本文“Java中通过Emit实现动态类生成[Java编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

动态生成一个类关于AOP,O/R Mapping等技术非常有帮忙.关于Java来说,问题不大,而关于.NET,则要麻烦些(主要麻烦在于实现代码的生成需求IL),故猜想这大概也是在AOP, O/R Mapping方面,Java走得略前的缘由吧.

麻烦归麻烦,非不能也,动态生成一个简单的类还不至于太难.

假定有以下接口:

interface IAnimal
{
 void move();
 void eat();
}

但愿能成立一个类生成器TypeCreator,并能以以下方法利用:

TypeCreator tc=new TypeCreator(typeof(IAnimal));
Type t = tc.build();
IAnimal myAnimal= (IAnimal)Activator.CreateInstance(t);
myAnimal.move();
myAnimal.eat();

首先,发现System.Reflection.Emit.TypeBuilder仿佛就是一个现成的类生成器. 不过TypeBuilder既没有实用的static办法,也不能在外部实例化.不过ModuleBuilder倒有一个DefineType()办法,可以得到TypeBuilder;而ModuleBuilder和TyperBuilder一个德行,不能直接成立,得从AssemblyBuilder的DefineDynamicModule()办法得到.追根溯源,AssemblyBuilder得从AppDomain的DefineDynamicAssembly()的得来.终究好在AppDomain供应了一个静态办法:AppDomain.CurrentDomain. 这一连串并非没有原理,范例是依靠于Module的,而Module依靠于Assembly,而Assembly则被AppDomain装载.所谓“皮之不存,毛将焉附”,为了成立Type这个“毛”,得先把Assembly,Module这些“皮”顺次构造出来:

using System;
using System.Reflection;
using System.Reflection.Emit;
public class TypeCreator
{
 private Type targetType;
 /// <summary>
 /// 构造函数
 /// </summary>
 /// <param name="targetType">被实现大概担当的范例</param>
 public TypeCreator(Type targetType)
 {
  this.targetType = targetType;
 }
 public Type build()
 {
  //获得当前AppDomain
  AppDomain currentAppDomain = AppDomain.CurrentDomain;
  //System.Reflection.AssemblyName 是用来表示一个Assembly的完好名称的
  AssemblyName assyName = new AssemblyName();
  //为要成立的Assembly定义一个名称(这里忽视版本号,Culture等信息)
  assyName.Name = "MyAssyFor_" + targetType.Name;
  //获得AssemblyBuilder
  //AssemblyBuilderAccess有Run,Save,RunAndSave三个取值
  AssemblyBuilder assyBuilder = currentAppDomain.DefineDynamicAssembly(assyName,AssemblyBuilderAccess.Run);
  //获得ModuleBuilder,供应String参数作为Module名称,随便设一个
  ModuleBuilder modBuilder = assyBuilder.DefineDynamicModule("MyModFor_"+targetType.Name);
  //新范例的名称:随便定一个
  String newTypeName = "Imp_"+targetType.Name;
  //新范例的属性:要成立的是Class,而非Interface,Abstract Class等,并且是Public的
  TypeAttributes newTypeAttribute = TypeAttributes.Class | TypeAttributes.Public;
  //声明要成立的新范例的父范例
  Type newTypeParent;
  //声明要成立的新范例要实现的接口
  Type[] newTypeInterfaces;
  //关于基范例能否为接口,作差别处理
  if(targetType.IsInterface)
  {
   newTypeParent = null;
   newTypeInterfaces = new Type[]{targetType};
  }
  else
  {
   newTypeParent = targetType;
   newTypeInterfaces = new Type[0];
  }
  //得到范例生成器
  TypeBuilder typeBuilder = modBuilder.DefineType(newTypeName,newTypeAttribute,newTypeParent,newTypeInterfaces);
  //以下将为新范例声明办法:新范例应当override基范例的所以virtual办法
  //得到基范例的全部办法
  MethodInfo[] targetMethods = targetType.GetMethods();
  //遍历各个办法,关于Virtual的办法,获得其签名,作为新范例的办法
  foreach(MethodInfo targetMethod in targetMethods)
  {
   //只挑出virtual的办法
   if(targetMethod.IsVirtual)
   {
    //得到办法的各个参数的范例
    ParameterInfo[] paramInfo = targetMethod.GetParameters();
    Type[] paramType = new Type[paramInfo.Length];
    for(int i=0;i<paramInfo.Length;i++)
     paramType[i] = paramInfo[i].ParameterType;
     //传入办法签名,得到办法生成器
     MethodBuilder methodBuilder = typeBuilder.DefineMethod(targetMethod.Name,MethodAttributes.Public|
       MethodAttributes.Virtual,targetMethod.ReturnType,paramType);
     //由于要生成的是具体类,所以办法的实现是必不可少的.而办法的实现是通过Emit IL代码来产生的

     //得到IL生成器
     ILGenerator ilGen = methodBuilder.GetILGenerator();
     //以下三行相当于:{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);
   }
  }
  //真正成立,并返回
  return(typeBuilder.CreateType());
 }
}


  以上是“Java中通过Emit实现动态类生成[Java编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:

  • 利用Javascript实现网页水印(非图片水印)
  • Java开辟环境的搭建
  • Ubuntu java安装与配置
  • 办理Ubuntu 10.04 Firefox3.6 Java浏览器插件不工作的问
  • Ubuntu重装后Java环境的设置
  • Sun Java进入Ubuntu 10.10软件中央
  • Ubuntu 10.10配置Java开辟环境
  • 在Ubuntu 10.10中配置Java环境变量的办法
  • Ubuntu下Java环境的搭建
  • Ubuntu 10.04 下安装 Java, JRE
  • Ubuntu 10.04下的搭建SUN JAVA开辟环境
  • Ubuntu 12.04安装java7
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        100%(1)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .