今天有点时间来研究那篇文章,就是关于可扩展性应用开发的,我可不管什么是插件,具体的定义我也不是很清楚,但是我知道开发一个程序,能够加入新的功能并能够执行这些功能是真的很牛的一件事情,当然我想做的不是插入什么漂亮的界面,我只是想学习一下,能够为程序增加很好的功能而不用触动现有的框架。
事实上,这篇文章也提到了“不管您的应用程序有什么用途,只要它是可扩展的,就必须执行三个基本任务……”,也就是说,无论我需要做的是什么样的扩展,我都应该遵循这个文章中介绍的这些技术。
顺便插一句,这个文章翻译得有些问题,有的地方读着感觉不够通顺。
言归正传,文章提到,这种应用开发的4个基础:CTS、Reflection、Fusion和CAS,也就是通用类型系统、反射技术、融合和代码访问安全性。
具体到实现可扩展性应用开发的时候,完成一个加入一个插件或成为plug-in的时候的具体步骤有3个,分别是:发现、加载和激活。每一个步骤都有相关的问题需要处理。
发现:文章首先确定了发现的具体含义,他说到“发现是查找应用程序在运行时绑定的插件和其他代码的过程”,也就是说,一个应用程序对于新的程序集实际上是一无所知的,它既不知道这个代码是什么样的,也不知道这个代码能做什么过程,简直就是盲人摸象,发现就是要摸清楚这个程序集的底细。然而这个发现过程有些自我矛盾,假设是在与主程序相同的程序域中,那么,首先要加载外部程序集才能够用主程序的代码去“摸底”,但是一旦加载就无法从主程序域中卸载这个程序集这一点毋庸置疑,.NET的框架结构中找不到动态卸载程序集的任何方法。于是,如果加载的程序集不对,也就是说不是主程序预想的那一种程序集怎么办,在内存中留着不用吗?比如主程序允许扩展界面,希望插件是能够提供新的作图手段的,但是用户加载了一个可执行文件,或者是一个通信程序,就会出现这种情况,主程序给出了提示,用户只好再从他的硬盘中找,再次试验,在找到真正要加载的程序集之前,也许已经向主程序的AppDomain中加载了很多程序集了,这种情况可是不妙啊。因此,这个发现过程有些自相矛盾。但是能够解决这个问题,就是使用专门的程序域来处理它。
加载:文章中对加载没有一个非常具体的定义,只是说“在运行时绑定到(Binding to code)代码”,在这一段中文章描述了AppDomian和Assembly,并且说明加载和发现的密切关系,正如上一段中我的理解。一个典型的先有鸡还是先有蛋的问题。这段文章中还说明了最重要的几个类都在System.Reflection这个命名空间当中。AppDomain、Type和Assembly这三个类是最重要的。
这一段中有一句翻译得不清楚原文“The Assembly.Load method returns a reference to the Assembly object. ”中的“a reference”就是一个引用,而在疑问中“一个”给丢掉了,这让人想当费解了。
文章解释了Assembly.Load和Assembly.LoadFrom方法,Assembly.Load是一个静态方法,它从AppDomain的AppBaseDir加载程序集,使用的是不带扩展名的文件名称。
文章说Assembly.LoadFrom要比Assembly.Laod的性能差,而且没有遵循程序集的发现过程的规则,除了插件程序之外其他类型的晚期绑定的应用使用Assembly.LoadFrom性能要差,我不知道发现和加载完成之后运行这段程序集的时候还会差吗。
接下来讲的这一段晚期绑定的过程我有些迷惑,对照了中英文的文章都没有太理解,先写到这里,晚上再看看。
接着写啊……
文章接下来就分析到了“发现”这个概念。顺便说一句,我觉得这里的译文最难以理解。
发现(Discovery),文章中给出的概念是“在运行时发现(find)代码”,这里面的概念我觉得至关重要,我按照我对原文的理解来写,译文仅作为参考了。
When compiling an application you explicitly or implicitly tell the compiler about code that your application binds to and uses at run time.
当编译应用程序时,您必须显式或隐式地告诉编译器,应用程序在运行时将要绑定到(binds to)的和要使用的代码的相关情况。
这些代码出现的形式是可广泛重用的类库类型(例如 Object、FileStream 和 ArrayList)以及打包在 helper 程序集中特定于应用程序的类型。
The compiler stores references to the assemblies that implement these types in your assembly's manifest, and the CLR references the manifest at run time in order to load all the necessary assemblies.
编译器将实现了类型的程序集的引用存储在程序集的清单中,然后CLR在运行时通过引用这个清单来加载所有必需的程序集。
MSDN中文版的译文然人很费解,是这样的:“编译器存储在程序集清单中实现这些类型的程序集的引用,而 CLR 在运行时引用该清单以加载所有必要的程序集。”
这就是典型的托管代码绑定过程……
NND,想来这样理解大概是对的。
文章讲完这些概念后开始步入实用阶段,这回真的要未完待续了,我想玩一会儿了……。