然后,你可以用ILDM查看一下这个配件中究竟定义了什么。
私有配件和共享配件之间有什么区别?
私有配件通常只被一个应用程序使用,一般它被保存在应用程序目录,或者其子目录下面.。而共享配件通常保存在全局的配件catch缓冲区中, 它是一个由.Net运行时环境维护的配件仓库。
共享配件通常是许多程序都要使用的代码库,比如.Net框架的类库就是如此。
事实上, 我们应该如下区分三种配件:
* 私有(private):
只对一个应用程序可见; 这是缺省配置, 其它的应用程序不能对其引用,这个配件必须在应用程序目录或者其子目录下面有个拷贝.
* 公有(public):
对其它的应用程序可见, 不管它在什么目录下面(可以是URL),其它的应用程序都可以对其直接引用.
* 公有共享(public shared):
Net环境怎样查找配件?
当然是按照路径查找, 规则如下:
* 在应用程序所在目录及其子目录下面私有配件
* 对于共享组件, 除了上面的规则, 再加上.Net提供的共享配件缓冲区路径.
配件怎样版本化?
我们已经知道所有的类型对象是使用全局的ID标识的, 那么配件是怎样版本化呢?
版本号分为4个部分(举例, 5.5.2.33). 分类如下:
不兼容: 前两个不同
可能兼容: 前两个相同, 第3个不同
兼容: 前三个相同, 第4个不同
如果你正确的编译你的代码,assembly就会以DLL或者EXE的形式保存在磁盘上。像这样保存在物理磁盘上的assembly被称为静态assembly。
当启动一个.NET应用程序的时候,程序首先要检查自己的安装目录中是否有需要的assembly,如果几个程序运行,那么每个都要在自己的安装目录中查找自己需要的assembly。也就是说每个程序都使用自己的assembly备份,这样的assembly称为私有assembly。它们只在应用程序的安装目录范围内有效。
一些情况下,你可以发现多个应用程序需要使用共享的assembly而不只是使用他们自己的,对这种情况,你可以在全局assembly缓存(译者:Global Assembly Cache,这个翻译有点不伦不类,大家明白就好)中管理该assembly(后面会提到)。这样的assembly在全局过程中有效,可以被机器内的所有程序共享,被称为共享Assembly。如果应用程序不能在自己的安装目录中得到需要的assembly,它将在全局assembly缓存中查找。如果愿意你可以考虑把你的assembly成为共享assembly。
Assembly可以把你从DLL地狱中解救出来。
Assembly支持并行(side-by-side execution)执行
这么说有点不好理解,不过很简单,也就是说同一assembly的不同版本可以在同一个机器上同时执行。不同的应用程序
Assembly是自描述的
配置简化
卸载容易
不需要注册表,当然简单的删掉就算是卸载了。
载创建一个assembly之前,我们先来了解一下assembly的组成结构。Assembly由以下几部分组成:
Assembly Manifest(译者:Assembly清单?不贴切,其实类似于一个目录或者入口)
包含assembly的数据结构的细节。
包含assembly中允许的类型数据。(前面提到过,class, interface,member, property等)
单文件和多文件Assembly
下面我们了解一下assembly manifest的更详细的信息。Assembly manifest保存了assembly细节的数据结构。对多文件assembly来说,assembly manifest好像一个“绑定器”把多个文件绑定到一个assembly中。请注意Manifest和Metadata并不相同,Metadata保存的是在assembly和module里用到的数据类型(如class, interface, method等)的相应信息,而Manifest是用来描述assembly本身结构的细节信息的。
对单文件Assembly来说,Manifest嵌在DLL或EXE文件内,对多文件assembly, Manifest可以内嵌在每个文件中也可以存在于一个委托(constituent)文件里。后面将会有详细说明。
下面列出了Manifest中的主要信息:
Metadata
Metadata数据是对assembly中数据的定义。每个EXE或DLL包含自己的详细的类型信息,这种数据叫Metadata。主要包括以下信息:
Modules
创建单文件Assemblies
创建多文件的Assembly
这里我们将建立一个叫CompanyStaff的assembly,包括两个类Clerk和Manager。下面我们看看创建多文件assembly的两种办法:
第一种方法是分别编译Clerk和Manager两个类到不同的modules中,然后把两个modules加到CompanyStaff DLL中去得到最终的assembly。这时CompanyStaff DLL将管理assembly manifest。这种方法可以用正常的命令行编译实现。(这里是CSC)
使用命令行编译器创建多文件assembly
我们将进行以下步骤:
Step1: 创建Clerk Module
用命令行编译这个类:
这里/t:module开关告诉编译器把代码编译成一个module。
用下面的命令行形式编译:
Step3: 创建CompanyStaff assembly
用下面的命令行形式编译:
Step4: 创建一个客户程序来使用assembly
用下面的命令行形式编译:
用AL工具创建一个多文件assembly
输入下面的命令行:
编译上面的代码并运行,你可以得到和前面的例子一样的结果。
共享式assembly和全局assembly缓存
到目前为止,我们看到的都是私有式的assembly。当然在.NET应用中,我们多数都在单独的使用一些私有式的assembly,然而有时候你可能会需要在很多个应用程序中共享一个单独的assembly的备份。我们前面提到过,共享assembly需要把assembly放到全局assembly缓存中去(Global Assembly Cache)。全局assembly缓存是磁盘上一个特殊的目录,一般它位于<driver>\WINNT\ASSEMBLY目录下。注意当安装过.NET后,这个目录在explorer下显示和其他目录有点不同,如果想看一下它的实际内容,你可以用命令行的形式来查看。
注意:不能简单的把你的assembly copy到这个目录下。首先你需要给你的assembly一个strong name,然后可以用AL把这个assembly安装到全局assembly缓存中去。
Strong Name
Versioning
向前面看到的那样,多数时候,.NET assembly被用作私有模式。对这样的assembly,因为它们都位于应用程序自己的目录下,所以versioning看起来并不是十分重要。然而对共享式assembly来说,versioning是很重要的。共享式assembly可以以并行的形式使用(前面提到过并行使用的概念),因此完全有可能在同一台机器上存在同一个assembly的不同版本。当应用程序要使用一个assembly时候,它就应该提供最近的或以前的版本的信息。如果开发者需要使用不同版本,就需要在代码中明确的设置版本号,其格式如下:
<major version>.<minor version>.<build number>.<revision>
Runtime将通过前两个参数来决定当前使用的版本是否和以前的版本兼容(major version和minor version)。如果这两个参数有变化,那么assembly将被认为是不兼容的,全局assembly缓存会为该assembly生成一个单独的入口,如果在代码中指定了版本号的话,major version就是可选的了。
下面显示了.NET如何将同一个assembly(EmployeeShared)的不同版本视为不同的assembly的例子。
创建一个共享式的assembly
现在你应该已经知道什么是共享式assembly了,下面我们将创建一个叫EmployeeShared的assembly。创建一个共享式assembly包括以下几个步骤:
Step1: 创建assembly代码并在代码中指定其版本号
我们创建了这个类,包含一个属性Name和一个方法GetSalary。注意AssemblyVersionAttribute的用法,它为该assembly设置了版本信息。
Step2: 用SN工具创建一个公钥/私钥对
为了给你的assembly赋一个Strong Name,你需要一个公钥/私钥对。可以使用.NET SDK提供的工具SN (Shared Name),输入以下命令行:
该命令在指定文件里创建了一个钥匙对,参数-k表示我们要把钥匙对写到输出文件里。
扩展名.SNK只是个习惯,你可以让它叫任何名字。
Step 3: 编译assembly并用上一步中创建的公钥/私钥对签名
你也可以在这个文件里加上我们前面提过的般本号属性而不用在源代码里指定。
Step4: 在全局assembly缓存中安装该assembly
我们的assembly已经用过私钥签名了,下面可以把它放在全局assembly缓存中了。像前面一样使用AL,命令行如下:
开关/I表示我们要将assembly安装到全局assembly缓存中。
好了,现在assembly被安装在全局assembly缓存并且可以使用了。想验证一下的话到explorer中看一下Assembly目录。
有时候你可能需要分析assembly,尤其是别人开发的assembly。这种情况下你可以使用一个叫ILDASM (Intermediate Language Disassembler)的工具。这个工具就象我们从前用过的OLE View或者VB的object viewer一样,你可以把你的assembly或者module导入这个工具来查看assembly各方面的特性,比如它包含的member, method和manifest。看起来就像下面这样。
你可以通过双击树结构中的节点得到更多的信息。
assembly是.NET的组成模块。.NET应用程序由一个或者多个assembly组成。一个.NET assembly由一个或多个文件组成并且在其自身的manifest中保存自己的注册信息。通常一个assembly只为一个应用程序服务,这样的assembly叫做私有式assembly。你也可以通过配置让一个assembly的copy为多个应用程序服务。这样的assembly叫做共享式assembly。共享式assembly在全局assembly缓存中被管理。共享式assembly必须有一个在整个机器范围内唯一标识的strong name。