当前位置:主页   - 电脑 - 网站开发 - ASP.Net
Emit学习-基础篇-基本概念介绍
来源:网络   作者:   更新时间:2012-03-26
收藏此页】    【字号    】    【打印】    【关闭

  本文示例源代码或素材下载

  之前的Hello World例子应该已经让我们对Emit有了一个模糊的了解,那么Emit到底是什么样一个东西,他又能实现些什么功能呢?昨天查了点资料,大致总结了下,由于才开始学习肯定有不完善的地方,希望大家能够批评指正。

  1.       什么是反射发出(Reflection Emit)

  Emit应该是属于反射中的一个比较高级的功能,说到反射大家应该都不陌生,反射是在运行时发现对象的相关信息,并且执行这些对象(创建对象实例,执行对象上的方法)。这个功能是由.NET的System.Reflection命名空间的类所提供的。简单的说,它们不仅允许你浏览一个程序集暴露的类、方法、属性和字段,而且还允许你创建一个类型的实例以及执行这些类型上的方法(调用成员)。这些特性对于在运行时对象发现,已经很了不起了,但.NET的反射机制并没有到此结束。反射还允许你在运行时构建一个程序集,并且可以创建全新的类型。这就是反射发出(reflection emit)。

  使用Emit可以从零开始,动态的构造程序集和类型,在需要时动态的生成代码,提高程序的灵活性。有了这些功能,我们可以用其来实现一些典型的应用,如:

  l  动态代理(AOP);

  l  减少反射的性能损失(Dynamic Method等);

  l  ORM的实现;

  l  工具及IDE插件的开发;

  l  公共代码安全模块的开发。

  2.       使用Emit的完整流程

  使用Emit一般包括以下步骤:

  1)        创建一个新的程序集(可以选择存在与内存中或者持久化到硬盘);

  2)        在程序集内创建一个模块;

  3)        在模块内创建动态类;

  4)        给动态类添加动态方法、属性、事件,等;

  5)        生成相关的IL代码;

  6)        返回创建出来的类型或持久化到硬盘中。

  当然如果你只是想要创建一个Dynamic Method 那么可以直接使用之前HelloWorld例子中使用的DynamicMethod类来创建一个动态方法,并在构造函数时传入它所依附的类或者模块。看了这个流程,相信大家已经对用使用Emit来创建动态类型的过程有了一个直观的认识,下面我们就通过实现一个求斐波那契数列的类来加深对这一流程的了解。

  在开始我们的例子之前,先给大家介绍一款反编译软件Reflector,使用这个软件可以给我们编写IL代码提供很大的帮助。

  接下来我们按照上面所说的流程来创建我们的斐波那契类:

  第一步:构建程序集

  要构建一个动态的程序集,我们需要创建一个AssemblyBuilder对象,AssemblyBuilder类是整个反射发出工作的基础,它为我们提供了动态构造程序集的入口。要创建一个AssemblyBuilder对象,需要使用AppDomain的DefineDynamicAssembly方法,该方法包括两个最基本的参数:AssemblyName和AssemblyBuilderAccess前者用来唯一标识一个程序集,后者用来表示动态程序集的访问方式,有如下的成员:

  成员名称

  说明

  Run

  表示可以执行但不能保存此动态程序集。

  Save

  表示可以保存但不能执行此动态程序集。

  RunAndSave

  表示可以执行并保存此动态程序集。

  ReflectionOnly

  表示在只反射上下文中加载动态程序集,且不能执行此程序集。

 

  在这里我们选择使用RunAndSave,完整的代码如下:

  #region Step 1 构建程序集

//创建程序集名
AssemblyName asmName = new AssemblyName("EmitExamples.DynamicFibonacci");

//获取程序集所在的应用程序域
//你也可以选择用AppDomain.CreateDomain方法创建一个新的应用程序域
//这里选择当前的应用程序域
AppDomain domain = AppDomain.CurrentDomain;

//实例化一个AssemblyBuilder对象来实现动态程序集的构建
AssemblyBuilder assemblyBuilder = domain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
#endregion

  第二步:定义模块(Module)

  与第一步类似,要定一个动态模块,我们需要创建一个ModuleBuilder对象,通过AssemblyBuilder对象的DefineDynamicModule方法,;要传入模块的名字(如果要持久化到硬盘,那么还需要传入要保存的文件的名字,这里就是我们的程序集名),这里我们使用程序集名作为模块名字:

  #region Step 2 定义模块

<code>ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name, asmFileName);

   第三部:创建一个动态类型

  这个时候恐怕我不说你也已经知道了,对,现在我们就是要用ModuleBuilder来创建一个TypeBuilder的对象,如下:

  #region Step 3 定义类型

TypeBuilder typeBuilder = moduleBuilder.DefineType("EmitExamples.DynamicFibonacci", TypeAttributes.Public);
#endregion

  这里EmitExamples表示名字空间,DynamicFibonacci是类的名字,TypeAttributes表示类的属性,可以按照实际需要进行组合。

  第四步:定义方法

  到这里为止,我们的准备工作已经差不多了,下面要开始真正的大展拳脚啦!

  我们先来看一下我们接下来要实现的动态类C#代码的实现,然后再以这为目标进行动态构建:

Fibonacci
public class Fibonacci
{
    public int Calc(int num)
    {
        if (num == 1

其它资源
来源声明

版权与免责声明
1、本站所发布的文章仅供技术交流参考,本站不主张将其做为决策的依据,浏览者可自愿选择采信与否,本站不对因采信这些信息所产生的任何问题负责。
2、本站部分文章来源于网络,其版权为原权利人所有。由于来源之故,有的文章未能获得作者姓名,署“未知”或“佚名”。对于这些文章,有知悉作者姓名的请告知本站,以便及时署名。如果作者要求删除,我们将予以删除。除此之外本站不再承担其它责任。
3、本站部分文章来源于本站原创,本站拥有所有权利。
4、如对本站发布的信息有异议,请联系我们,经本站确认后,将在三个工作日内做出修改或删除处理。
请参阅权责声明