使用程序集和模块

 

程序集预览(Assembly Overview       

        任何.NET二进制代码使用的.NET运行时是一个或一组程序集组成的。当你编译一个应用程序时,实际上是在创建一个程序集。

        任何时候构建一个EXEDLL文件时必须使用/t:library编译参数创建与该应用程序相对应的包含清单(manifest)的程序集,清单(manifest)记录了.NET运行时程序集的相关信息。另外,使用/t:module编译参数,创建一个以.netmodule为扩展名的DLL 文件,这个DLL文件不包含清单。换句话说,虽然逻辑上模块(module)依然是一个DLL文件,但是它不属于程序集,当编译应用程序或使用程序集生成工具(the Assembly Generation tool)时必须使用/addmodule开关将这个DLL文件加入到其他程序集中。

清单数据(Manifest Data

       程序集的清单有不同的方法存储。若编译一个独立的应用程序或DLL文件,清单与程序或DLLPE结合在一起,这称为单一文件的程序集(single-file assembly)。多文件程序集(multifile assembly)是指清单以另外一个独立实体的形式作为程序集的一部分,或者作为程序集中的一个模块。

       同样程序集的定义很大程度取决你如何使用它。从客户的角度来看,程序集是模块、导出类型、(必需、可选)资源的命名和版本化(versioned)的集合。从程序集创建者的角度来看,程序集是客户能使用的一组相关联的模块、类型、资源、导出的方法的封装包(mean of packaging)。也就是说,清单是程序集和用户之间沟通的桥梁。下面列出程序集中清单包含的信息:

·          程序集名称(Assembly name

·          版本信息(Versioning information

        版本信息是由四个不同的部分组成的版本号,分别是主版号、子版号、构建序号、修订号。

·          (可选的)共享名和带符号的程序集散列(AnOptionalshared name and signed assembly hash

        主要是关于程序集部署的相关信息。

·          文件(Files

         包含在程序集中的文件列表。

·          引用的程序集(Referenced assemblies

         直接引用的外部程序集列表。

·          类型(Types

        程序集内部的所有类型及模块映像包含的类型的列表。(This is list of all types in the assembly with a mappig to containing the type.

·          安全(Security

        安全权限的列表,权限已明确地被程序集抛弃。(permissions This is a list of security permissions that are explicity refused by the assembly.

·          定制属性(Custom attributes

·          产品信息

        包含公司、商标、产品及版权信息。

 

程序集的优势

·          程序集的封装:将多个模块封装到一个物理文件,起到性能优化的作用。当你创建一个应用程序并使用多文件程序集时,.NET运行时只需加载相关的模块。这种策略起到减少应用程序的工作集。

·          程序集的部署

             .NET框架中程序集是最小的部署单元。虽然它诱人的说,程序集是部署应用程序的方法,但是技术上并不是如此。许多关于程序集部署的正确的观点是:在.NET中程序集应该看作一个窗体的类部署(class deployment)-就像Win32中的一个DLL文件。一个单独的应用程序是由多个程序组成的。

             因为程序集是自描述的(self-desciribing),所以部署程序集最简单的方法就是直接把程序集复制到目的文件夹。当尝试运行包含这个程序集的应用程序时,清单将向.NET运行时提供包含在这个程序集中的方法信息。另外,清单(manifest)也向应用程序提供该程序集所引用的外部程序集的相关信息。

             许多通过公共方法部署的程序集依然是私有的程序集,即程序集被复制到文件夹,但它们不是共享的。缺省情况下程序集是私有的,除非明确地指定程序集为共享程序集(shared assembly)。

·          程序集的版本

             使用程序集另外一个主要优势是程序集内置了版本号。程序集中止了DLL地狱。DLL地狱是指当一个应用程序重写了一个被其他应用程序引用的DLL文件,而该应用程序引用的是低版本的同名DLL文件,这就造成了引用低版本DLL的应用程序运行出错,这种情况。虽然Win32资源文件格式内置了版本资源类型,但是操作系统不会强制执行任何版本控制,以便依赖这个DLL文件的应用程序能正常运行。

             基于这个问题,清单不仅包含程序集本身的版本信息,也包含了该程序集所有被引用的程序集和这些程序集的版本信息。因为有了这个体系结构,.NET运行时能确保版本规则被支持,当出现新版本的程序集时,版本不兼容的共享DLLs由操作系统自动安装,使得应用程序可以继续正常运行。

// DllTestServer.cs
// Build with the following command-line switches:
//     csc /t:library DllTestServer.cs
public class DllTestServer
{
    
public static void Foo()
    
{
        System.Console.WriteLine(
"DllTestServer.Foo " +
            
"(DllTestServer.DLL)");
    }

}


// DllTestClient.cs
// Build with the following command-line switches:
//     csc DllTestClient.cs /r:DllTestServer.dll 
using System;
using System.Diagnostics;
using System.Reflection;

class DllTestClientApp
{
    
public static void Main()
    
{
        Assembly DLLAssembly 
=
            Assembly.GetAssembly(
typeof(DllTestServer));
        Console.WriteLine(
"\nDllTestServer.dll Assembly " +
            
"Information"); 
        Console.WriteLine(
"\t" + DLLAssembly);

        Process p 
= Process.GetCurrentProcess();
        
string AssemblyName = p.ProcessName + ".exe";
        Assembly ThisAssembly 
= Assembly.LoadFrom(AssemblyName);
        Console.WriteLine(
"DllTestClient.exe Assembly " +
            
"Information"); 
        Console.WriteLine(
"\t" + ThisAssembly + "\n");

    Console.WriteLine(
"Calling DllTestServer.Foo");
    DllTestServer.Foo();
    }

}

 

用多个模块创建程序集(Creating Assembies with Multiple Modules

   模块是基于DLL,但是它不是真正意义上的DLL,它必须被包含程序集中。示例:
// NetModuleTestServer.cs
// Build with the following command-line switches:
//     csc /t:library NetModuleTestServer.cs
public class NetModuleTestServer
{
    
public static void Bar()
    
{
        System.Console.WriteLine(
"NetModuleTestServer.Bar(NetModuleTestServer.netmodule)");
    }

}


// NetModuleTestClientApp.cs
// Build with the following command-line switches:
//
// csc addmodule:NetModuleServer.netmodule NetModuleTestClientApp.cs
using System;
using System.Diagnostics;
using System.Reflection;

class NetModuleTestClientApp
{
    
public static void Main()
    
{
        Assembly DLLAssembly 
= Assembly.GetAssembly(
            
typeof(NetModuleTestServer));
        Console.WriteLine(
"\nNetModuleTestServer.dll Assembly " +
            
"Information");
        Console.WriteLine(
"\t" + DLLAssembly);

        Process p 
= Process.GetCurrentProcess();
        
string AssemblyName = p.ProcessName + ".exe";
        Assembly ThisAssembly 
= Assembly.LoadFrom(AssemblyName);
        Console.WriteLine(
"NetModuleTestClient.exe Assembly " +
            
"Information");
        Console.WriteLine(
"\t" + ThisAssembly + "\n");

        Console.WriteLine(
"Calling NetModuleTestServer.Bar");
        NetModuleTestServer.Bar();
    }

}


 

创建共享程序集

   若要创建一个在多个应用程序使用的程序集,并且版本信息相当重要,则必须共享程序集。若要共享程序集,必须给程序集指定强名称。可以通过.NET SDK提供强名称工具(the Strong Name tool)创建强名称。使用强名称有四个主要理由:

·          它是.NET生成唯一的全局名称的机制

·          因为强名称工具生成的密钥对包含了一个签名,你可以判断程序集创建之后是否被篡改。(Because the generated key pair includes a singature,you can tell whether an assembly has been tampered with after its original creation.

·          强名称能防止第三方在你构建的程序集的基础上发表新的版本。这是因为密钥对包含签名起了作用,因为第三方不知道你的私钥。

·          .NET加载程序集时,运行时会自动验证调用者是否合法。(When .NET load an assembly,the runtime can verify that the assembly came from the publisher that the caller is expecting.

创建强名称的步骤:

·          使用强名称工具为程序集创建一个强名称。示例:

    sn -k InsideCSharp.key

·          在客户端源代码文件中添加属性AssemblyKeyFile,把强名称指定给程序集。

 

使用全局程序集缓存工作

   .NET每次加载程序集时都会创建一个代码缓存区,通常成为全局程序集缓存。使用全局程序集缓存有三个作用:

·          存储从Internet或文件服务器下载的代码。注:从一个特定的应用程序加载的代码存储在缓冲中的私有区域,以防止其他程序集访问。

·          存储被多个.NET应用程序共享的组件数据。利用全局缓存工具将程序集加载到缓存全局区域,使得该程序集可以被本地机器的所有应用程序访问。

·          程序集的本地代码是预运行时编译的,同时存储在全局程序集缓存区。(native code versions of assemblies that have been preJITted are stored in the cache.

 

缓存视图

1、在windows\assembly文件夹中可以查看程序集的相关信息,如版本号、语言(culture)、公钥标记等等信息。

2、在命令行使用gacutil。其中-i参数:加载程序集;-u参数:卸载程序集(可以指定版本号)、-l参数:列出程序集的相关信息。
posted @ 2005-08-25 09:33  清香的工夫茶  阅读(1856)  评论(1编辑  收藏  举报