资源大全 | 神秘文化 | 在线翻译 | QQ专区 | 视频教程 | 彩信频道 | 搜索引擎 | BT下载 |  | 网站地图
设为首页
加入收藏
联系站长
您现在的位置: 一百网络 >> ASP.NET编程 >> E-mail专题 >> 文档正文
最近更新
普通文档 Email发送完全手册
普通文档 一个发邮件的例子,涉及M
普通文档 一段VB.NET代码,生成邮件
普通文档 改进了的一个邮件发送类
推荐文档 通过Emit实现动态类生成
普通文档 在Web上利用System.Web.
普通文档 使用System.Web.Mail通过
普通文档 在.NET 应用程序中用Sys
推荐文档 asp.net中使用JMail发邮
推荐文档 asp.net中使用JMail发邮
推荐文章
推荐文档 通过Emit实现动态类生成
推荐文档 asp.net中使用JMail发邮
推荐文档 asp.net中使用JMail发邮
通过Emit实现动态类生成

文章作者:佚名 录入时间:2006-6-13 来源:不详
网站声明:本站的文章除部分特别声明禁止转载的专稿外,可以自由转载.但请务必注明出处和原始作者,文章版权归本网站与文章作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。


动态生成一个类对于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());
}
}

好了,测试一下试试看:using System;

public class Tester
{
public static void Main(String[] args)
{
TypeCreator tc=new TypeCreator(typeof(IAnimal));
Type t = tc.build();
IAnimal animal= (IAnimal)Activator.CreateInstance(t);
animal.move();
animal.eat();

Console.Read ();
}
}

得到输出:I'm moveingI'm eating 总结:如果用于AOP的话,Emit可以动态生成一个装饰类,相比于基于Remoting架构的TP/RP的方法,效率可能要高些,而且还能拦截new操作符。缺点:对于非Virtual的方法,似乎无法拦截。用于O/R Mapping的类生成,倒是不错

  • 上一篇文档:

  • 下一篇文档:
  •     查找更多“通过Emit实现动态类生成”的内容  
    相关连接
  • 24点的算法

  • Win2003创建WEB应用程序出现错误的解决办法

  • 使用 ASP.NET 加密口令

  • Email发送完全手册

  • 一个发邮件的例子,涉及MSMQ,RSA,JMAIL