帝国软件
  设为首页 加入收藏 关于我们
 
解密帝国网站管理系统
栏 目:
 
您的位置:首页 > 技术文档 > ASP.NET编程 >
Assembly学习心得(2)
作者:王雪鹏 发布时间:2005-03-12 来源: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 感谢刘琳的大力帮助。
  
   <END>
  

  
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
 ·第十五节--Zend引擎的发展 -- Cl  (2005-03-11)
 ·第十四节--命名空间 -- Classes   (2005-03-11)
 ·第十三节--对象串行化 -- Classe  (2005-03-11)
 ·第十二节--类的自动加载 -- Clas  (2005-03-11)
 ·第十一节--重载 -- Classes and   (2005-03-11)
 ·第十节--抽象方法和抽象类 -- Cl  (2005-03-11)
 ·第九节--绑定 -- Classes and Ob  (2005-03-11)
 ·第八节--访问方式 -- Classes an  (2005-03-11)
 ·第七节--类的静态成员 -- Classe  (2005-03-11)
 ·第六节--访问属性和方法 -- Clas  (2005-03-11)

   栏目导行
  PHP编程
  ASP编程
  ASP.NET编程
  JAVA编程
   站点最新
·致合作伙伴的欢迎信
·媒体报道
·帝国软件合作伙伴计划协议
·放眼未来 帝国近期将有重大举措!
·PHPWind6.3.2版通行证发布
·帝国备份王2008版正式发布
·帝国备份王2008版发布
·phpcms2007转帝国CMS5.0程序发布
·dedecms5.1转帝国CMS5.0程序发布
·帝国网站管理系统V5.0商业购买说明
   类别最新
·ASP.NET中为DataGrid添加合计字段
·.text urlRewrite介绍
·利用 ASP.NET 的内置功能抵御 Web
·ASP.NET Cache
·用 WebClient.UploadData 方法 上载
·ASP.NET 程序设计-序
·什么是客户端/伺服端(Client/Serve
·因特网应用程序的开发
·网页的种类
·.NET Framework-Microsoft Visual
 
关于帝国 | 广告服务 | 联系我们 | 程序开发 | 网站地图 | 留言板 帝国网站管理系统