Assembly学习心得(2)

Assembly学习心得(2)


作者: 王雪鹏    来源:aspcool    第二部分(例子)      下面是一个完整的例子来逐一说明上面所提到的概念,以加深理解。    整个例子包含7个文件(在主目录下):    主目录为 …/Assembly ----源程序目录    …/Assembly/Bin ---- 编译结果输出的目录,也就是应用程序主目      录。            文件名    类型    说明      App.cs    Code源文件    主程序,包含程序入口,    属于namespace1      ClassA.cs    Code源文件    类型A,包含一个静态方法,    属于namespace1      ClassB.cs    Code源文件    类型B,包含一个静态方法,    属于namespace2      AssemblyInfo.cs    Code源文件    包含程序集签名信息,    版本信息等      App.Key    公钥/私钥对文件    用来给程序集签名,    生成强命名程序集      App.PublicKey    只包含共有密钥    只储存共有密钥,    用SN.exe来查看      App.exe.config    Xml格式配置文件    App.exe的应用程序配置文件      源代码    App.cs    namespace namespaceA {    public class App {    static void Main (string[] args) {    System.Console.WriteLine(ClassA.ShowMe());    System.Console.WriteLine(namespaceB.ClassB.ShowMe());    }    }    }    ClassA.cs    namespace namespaceA {    public class ClassA {    public static string ShowMe()    {    return "This is ClassA";    }    }    }      ClassB.cs    namespace namespaceB {    public class ClassB {    public static string ShowMe() {    return "This is ClassB";    }    }    }    AssemblyInfo.cs    ////////////////////////////////////////////////////////////////////////////////    // Module: AssemblyInfo.cs    ////////////////////////////////////////////////////////////////////////////////    using System.Reflection;    ////////////////////////////////////////////////////////////////////////////////    // Set CompanyName, LegalCopyright, and LegalTrademarks    [assembly: AssemblyCompany("App Company")]    [assembly: AssemblyCopyright("Copyright (C) 2004 @ App Company")]    [assembly: AssemblyTrademark("App is a test only program")]    ////////////////////////////////////////////////////////////////////////////////    // Set ProductName and ProductVersion    [assembly: AssemblyProduct("App Product")]    [assembly: AssemblyInformationalVersion("1.0.0.0")]    ////////////////////////////////////////////////////////////////////////////////    // Set FileVersion and AssemblyVersion      [assembly: AssemblyFileVersion("1.0.0.0")]    [assembly: AssemblyVersion("1.0.0.0")]    [assembly: AssemblyTitle("App type assembly")]    [assembly: AssemblyDescription("App Aassembly is a test only assembly")]      ////////////////////////////////////////////////////////////////////////////////    // Set Culture    [assembly: AssemblyCulture("")]    [assembly: AssemblyDelaySign(false)]    [assembly: AssemblyKeyFile("App.key")]    [assembly: AssemblyKeyName("")]    App.key和App.PublicKey是二进制格式存储的,不能直接查看。后面例子中会用到      1. 把源代码编译为托管模块(Managed Module)    csc /out:bin/classA.module /t:module classA.cs    参数:    /out: 输出路径    /t: 输出格式。可以有四种,分别是:    library ---- DLL程序集    exe ---- 控制台可执行程序(也是程序集的一种)    winexe ---- Windows可执行程序(同样也是程序集的一种)    module ---- 托管模块(程序集的一部分)      说明: 托管模块的的扩展名可以是任意的(也可以没有),因为编译的时候都是以元数据的格式读取的。      2. 把源代码编译为程序集(Assembly)    l 把ClassB编译为一个单文件程序集    csc /out:bin/classB.dll /t:library classB.cs    l 把App.cs,ClassA.module和ClassB.dll编译为一个多文件程序集    csc /out:bin/App.exe /t:exe app.cs /addmodule:bin/classA.module /r:bin/classB.dll    参数:    /addmodule: 把托管模块添加到程序集中 /r: 添加引用说明: 上面生成的程序集因为没有经过公钥/私有签名,所以生成的是非强命名类型的程序集。 生成的程序集App.exe的清单中只包含对classA.module托管模块的说明,并不 包classA.module的元数据,所以App.exe和classA.moudle必须在同一目录中。App.exe在运行时,如果用到对classA.module中类型的引用,则会去classA.moudel文件进行查找,如果classA.moude文件不存在,则会引发System.IO.FileNotFoundException。如果App.exe不会用到class.module中的类型,则classA.module存不存在都不会对App.exe的执行产生任何影响(这就是上面提到的Assembly的好处之一,Assembly只是一个逻辑上的组合)。    App.exe还用到了对ClassB.dll的引用,因为classB.dll不是一个强命名类型,所以它只能进行私有部署,可以和App.exe放在一起,也可以放在主目录下的其他子目录下。(后面通过应用程序更改配置文件,可以重定向指classB.dll的引用)。      3. 更改应用程序配置文件(App.exe.config),重定向对classB.dll的引用。      现在App.exe,classA.moudle和classB.dll都在Bin目录下,app.exe在运行时会找到所有它需要的类型,所以运行正常。      如果把在Bin目录下新建一个目录,比如sub,并把classB.dll移动到sub目录下,再运行App.exe就会出错。同样会引发System.IO.FileNotFoundException错误,因为App.exe运行时需要的classB类型找不到。这时候就需要更改添加(如果没有)或更改应用程序配置文件,应用程序配置文件是一个xml格式的配置文件,和web.config文件的作用差不多,是配置应用程序运行时的行为的。      注意:配置文件的名字必须是应用程序名字再加一个.config,且必须在同一目录下    详细信息参考: ms-help://MS.MSDNQTR.2004APR.1033/cpguide/html/    cpconnetapplicationconfigurationscenarios.htm      App.exe.config文件的内容:    <?xmlversion="1.0"encoding="utf-8"?>    <configuration>    <runtime>    <assemblyBindingxmlns="urn:schemas-microsoft-com:asm.v1">    <probingprivatePath="sub"/>    </assemblyBinding>    </runtime>    </configuration> 当App.exe运行时,它就会在主目录下的sub目录中找到classB.dll,然后继续行。    说明:    当CLR需要定位一个程序集时,它将扫描应用程序的几个子目录,下面是才CLR扫描一个程序集时的顺序:    …/Assembly/Bin/classB.DLL.    …/Assembly/Bin/classB/classB.DLL.    …/Assembly/Bin/sub/classB.DLL.    …/Assembly/Bin/sub/classB/classB.DLL.    …/Assembly/Bin/classB.EXE.    …/Assembly/Bin/classB/classB.EXE.    …/Assembly/Bin/sub/classB.EXE.    …/Assembly/Bin/sub/classB/classB.EXE.      注意: 如果App.exe引用的是强命名程序集,CLR会首先在GAC中查找,然后才按照上面的顺序查找。      4. 创建和查看公钥/私钥对文件    创建公钥/私钥对文件可以用.NET SDK自带的工具(SN.exe)来创建。 首先,创建一个公钥/私钥对文件    SN -k App.key    然后,用这个文件创建只包含共有密钥的文件:    SN -p App.key App.publickey    然后用-tp参数查看    SN –tp App.publickey   

    5. 创建强命名程序集    有了公钥/私钥对,创建强命名程序集就很容易了。只需要把    System.Reflection.AssemblyKeyFileAttribute特性加到源代码中就可以了。    [assembly: AssemblyKeyFile("App.key")]    一般都加到AssemblyInfo.cs文件中。    现在重新build classB.cs,得到的将是一个强命名的程序集:    csc /out:bin/classB.dll /t:library classB.cs AssemblyInfo.cs      用ILDasm.exe查看,你会发现,在Assembly中的Public Key会有一大串值,这个就是程序集的公有密钥,它保证了整序集的唯一性。    [img][/img]    6. 把强命名的程序集classB.dll加入到GAC中。    使用工具GACUtil.exe    把classB.dll加入到GAC中:    GACUtil /I classB.dll    删除掉classB.dll,然后重新Build App.exe:    csc /out:bin/app.exe /t:exe app.cs /addmodule:bin/classA.module /r:classB.dll    App.exe运行正确,表明classB.dll已经成功加入到GAC中,成为一个共享程序集了。 程序集相互引用的规则:      程序集种类    是否可以引用弱命名程序集    是否可以引用强命名程序集      普通程序集    是    是      强命名程序集    否    是          把classB.dll移出GAC: GACUtil /u classB    注意:    移出的时候不能指定扩展名(因为在GAC中每一程序集对于对应的都是一个目录,而不是实际的程序集)。      如果classB.dll不是一个强命名的程序集,而你想把app.exe build为一个强命名的,就会出错:    error CS1577: Assembly generation failed -- Referenced assembly 'ClassB' does not have a strong name    你可以试一试。J      7. 并行执行(Side-By-Side)的例子    http://www.microsoft.com/china/msdn/archives/library/    dnnetdep/html/sidexsidenet.asp      参考资料:    l Applied Microsoft .NET Framework Programming ---- Jeffrey Richter    l MSND Library    l 感谢刘琳的大力帮助。        (2005-11-01:05:01)

 感谢原创者的辛勤劳动,希望对您有所帮助,转载请注明原出处。
 您可能对 [Visual Studio.NET] 的这些文章也感兴趣:

全国省份,城市,地区全数据(SQL版与XML版)包括各城市邮编
LCS使用RTC API 发送IM消息的WebService
Visual studio tools for office体系结构
MindScape发布域建模和ORM工具LightSpeed 2.0
.Net类库中实现的HashTable
.net多语言和数据集内多数据表的处理(3)
多线程、Socket技术及委托技术的关系
.Net中的异步编程模式 (APM) (一)
让flex3与flash cs3珠联璧合协作开发
Visual Studio终于开始关注性能问题