乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      C#程序集(assembly)(精)

       悟靜 2012-05-02

      程序集

      ===============================================================================================
           ----------------------------------------------------------------------1 什么是程序集? ----------------------------------------------------------------------
      DLL的版本問題,程序不知道到底該使用哪個(gè)DLL版本,從而產(chǎn)生中斷。
      DLL-Hell----〉與DLL相關(guān)的問題
      .NET對DLL-Hell及其所有問題的答案是使用程序集
      程序集-是自我描述的安裝單元,由一個(gè)或多個(gè)文件組成,一個(gè)程序集可以是一個(gè)包括元數(shù)據(jù)的DLL或EXE,也可以由多個(gè)文件組成。
      另一優(yōu)點(diǎn)是可以使私有或共享的。
      私有程序集和共享程序集有很大的區(qū)別
      版本沖突問題必須在開發(fā)階段解決
      程序集的特性: 1 程序集是自我描述的;
            2 版本的互相依賴性在程序集的清單中進(jìn)行了記錄
            3 程序集可以進(jìn)行并行加載 ,同一個(gè)DLL的不同版本可以在同一個(gè)系統(tǒng)上同時(shí)使用
            4 應(yīng)用程序使用應(yīng)用程序域來確保其獨(dú)立性(Application Domain)
            5 安裝非 常簡單,只要復(fù)制一個(gè)程序集中的所有文件,一個(gè)xcopy命令就夠了--無干涉部署(No-touch Deployment)

      應(yīng)用程序集和應(yīng)用程序域

            -----------------------   |     ----------------------------
             進(jìn)程一       進(jìn)程二
      ____________   |   ____________
      應(yīng)用程序域A
      應(yīng)用程序域B   |
            ......
      ____________   |   ____________
          -------------------------     ----------------------------
      進(jìn)程之間有邊界,應(yīng)用程序域存在于某個(gè)進(jìn)程中,之間也有邊界,處在不同應(yīng)用程序域中的應(yīng)用程序不能互相訪問
      應(yīng)用程序域可以互相包含

      ------------------------------------------
      ======================
      進(jìn)程〉應(yīng)用程序域〉程序集〉對象
      ======================
      ------------------------------------------
      應(yīng)用程序域之間可以通信,或使用代理
      AppDomain類用于創(chuàng)建和中斷應(yīng)用程序域,加載和卸載程序集和類,枚舉域中的程序集和線程
      例如: 1--創(chuàng)建一個(gè)控制臺應(yīng)用程序AssemblyA
      2--第二個(gè)應(yīng)用程序DomainTest加載AssemblyA.exe程序集
      /////////////////////////////////////////////////////////////////////////////////////////
      using System;
      namespace Wrox.ProCSharp.Assemblies.AppDomains
      {
         class Class1
         {
          public Class1(int val1,int val2)
          {//構(gòu)造函數(shù),具有兩個(gè)參數(shù),以了解如何創(chuàng)建AppDomain類的實(shí)例
           Console.WriteLine("Constructor with the values {0},{1}"+
             "in domain {2} called",val1,val2,
             AppDomain.CurrentDomain.FriendlyName);
          }
          [STAThread]
          static void Main(string[] args)
          {//在Main中,從而知道什么時(shí)候調(diào)用Console.WriteLine
           Console.WriteLine("Main in domain {0} called",
             AppDomain.CurrentDomain.FriendlyName);
          }
         }
      }
      //////// /////////////////////////////////////////////////////////////////////////////////
      using System;
      namespace Wrox.ProCShap.Assemblies.AppDomains
      {
         class Test
         {
          [STAThread]
          static void Main(string[] args)
          {
           AppDomain currentDomain = AppDomain.CurrentDomain;
           Console.WriteLine(currentDomain.FriendlyName);
           //使用AppDomain類的FriendlyName屬性顯示當(dāng)前域的名稱

           ////FLAG////
           AppDomain.secondDomain = AppDomain.CreateDomain("New AppDomain");
           //創(chuàng)建一個(gè)新的應(yīng)用程序域New AppDomain

           secondDomain.ExecuteAssembly("AssemblyA.exe");
           //把程序集AssemblyA加載到新域中,通過調(diào)用ExecuteAssembly來調(diào)用Main()方法
          }
         }
      }

      在啟動(dòng)DomainTest.exe前,必須把程序集AssemblyA.exe復(fù)制到DomainTest.exe所在的目錄下,這樣程序才能找到
      這個(gè)程序集,不能添加AssemblyA.exe程序集的引用,因?yàn)樵赩S.NET中,只能給以DLL格式存儲(chǔ)的程序集添加引用,不支持
      EXE格式,但是EXE格式的程序集可以在命令行上執(zhí)行,如果找不到這個(gè)程序集就會(huì)拋出System.IO.FileNotFoundExection異常
      結(jié)果:Main in domain New AppDomain called

      在上面第二個(gè)程序表明的FLAG處可以改為:再創(chuàng)建一個(gè)實(shí)例,用于替代Main()方法
      /////////////////////////////////////////////////////////////////////////////////////////
      AppDomain secondDomain = AppDomain.CreateDomain("New AppDomain");

      secondDomain.CreateInstance("AssemblyA" ,"Wrox.ProCShap.Assemblies.AppDomains.Class1",
           true,System.Reflection.BindingFlags.CreateInstance,null,new object[]{7,3}
           null,null,null);
      /////////////////////////////////////////////////////////////////////////////////////////
      //1-程序集名;2-應(yīng)實(shí)例化的類;3-true表示不區(qū)分大小寫;4-邦定標(biāo)志枚舉值,指定應(yīng)調(diào)用的構(gòu)造函數(shù);
      得到的輸出為:Constructor with the values 7,3 in domain New AppDomain called


      在運(yùn)行期間主應(yīng)用程序域會(huì)自動(dòng)創(chuàng)建,
      ASP.NET為每個(gè)運(yùn)行在WEB服務(wù)器上的Web應(yīng)用程序創(chuàng)建一個(gè)應(yīng)用程序域,
      Internet Explorer創(chuàng)建運(yùn)行托管控件的應(yīng)用程序域,
      卸載應(yīng)用程序域只能通過中斷應(yīng)用程序域來進(jìn)行


           ----------------------------------------------------------------------2 程序集的結(jié)構(gòu) ----------------------------------------------------------------------
      程序集由=描述它的元數(shù)據(jù)(程序集元數(shù)據(jù))+描述導(dǎo)出類型和方法的類型元數(shù)據(jù)+MSIL代碼+資源
      存在于一個(gè)文件中或分布在多個(gè)文件中
      例如: 1 程序集由一個(gè)文件組成:Component.dll
      2 Component.dll=描述它的元數(shù)據(jù)+描述導(dǎo)出類型和方法的類型元數(shù)據(jù)+MSIL代碼,
         資源不在其中
         這個(gè)程序集使用了一個(gè)圖:Pictrue.jpeg,該圖沒有嵌入在dll中,而是在程序集的元數(shù)據(jù)中引用
         程序集的原數(shù)據(jù)還引用了一個(gè)模塊:Util.netmodule,該模塊只包含一個(gè)類的類型元數(shù)據(jù)和MSIL代碼
         不包含程序集的元數(shù)據(jù),所以這個(gè)模塊沒有版本信息,也不能單獨(dú)安裝
         這3個(gè)文件構(gòu)成了程序集,這個(gè)程序集是一個(gè)安裝單元,還可以在另外一個(gè)文件中放置程序集清單
          Component.dll   Util.netmodule
         ________________________ ____________
      Picture.jpeg<------- 程序集元數(shù)據(jù)   -------〉 類型元數(shù)據(jù)
      __________     -------〉 IL代碼
      資源   類型元數(shù)據(jù)   
         IL代碼

      程序集的清單
      元數(shù)據(jù)的一部分,描述了程序集和引用它所需的所有信息,并列出,了所有的依賴關(guān)系
      清單=標(biāo)識(名稱,版本,文化,公鑰)+屬于該程序集的一個(gè)文件列表+
      引用程序集的列表+一組許可請求--運(yùn)行的許可證+
      導(dǎo)出的類型(當(dāng)它們在一個(gè)模塊中定義,該模塊在程序集中引用,否則不屬于清單)

      ---------------------------------------------
      ======================
      命名空間,程序集和組件
      1 命名空間完全獨(dú)立于程序集
      2 一個(gè)程序集中可以有不同的命名空間
      3 一個(gè)命名空間也可以分布在多個(gè)程序集中
      4 命名空間只是類名的一種擴(kuò)展,它屬于類名的范疇
      ======================
      ---------------------------------------------

      ======================
      私有程序集和共享程序集
      在使用共享程序集時(shí),程序集必須是唯一的,名稱唯一(強(qiáng)名),該名稱的一部分是一個(gè)強(qiáng)制的版本號,如第三方控件
      ======================
      ======================
      查看程序集
      命令行工具:ILDASM

      FILE-->OPEN-->打開程序集
      ======================
      ======================
      構(gòu)建程序集
      1-可以創(chuàng)建模塊:csc /target:module hello.cs 模塊是一個(gè)沒有程序集特性的DLL,可以添加到程序集中
      創(chuàng)建了hello.netmodule
      2-生成一個(gè)程序集B.DLL ,它包含模塊A.netmodule: csc /target:library /addmodule:A.netmodule /out:B.dll
      3-模塊的作用1是可以更快的啟動(dòng)程序集,因?yàn)椴⒉皇撬蓄惗荚谝粋€(gè)文件中
         模塊只在需要時(shí)加載
      2是是否需要使用多種編程語言來創(chuàng)建一個(gè)程序集:一個(gè)模塊用VB.net,一個(gè)模塊用C#,這兩個(gè)模塊都包含在一個(gè)程序集中
      4-使用VS創(chuàng)建程序集
      VS2003不支持直接創(chuàng)建模塊
      創(chuàng)建一個(gè)項(xiàng)目時(shí),系統(tǒng)自動(dòng)生成源文件AssemblyInfo.cs,在該文件中可以使用一般的源代碼編輯器配置程序集的屬性
      [assembly]和[module]是程序集的全局屬性

      System.Reflection命名空間中的類:
      AssemblyCompany     ---指定公司名
      AssemblyConfiguration    --指定建立信息,例如零售或調(diào)試信息
      AssemblyCopyright/Assembly Trademark --包含版權(quán)和商標(biāo)信息
      AssemblyDefaultAlias    --如果程序集名稱不容易理解,如動(dòng)態(tài)創(chuàng)建程序集名稱時(shí)的GUID,就可以使用該屬性,指定一個(gè)別名
      AssemblyDescription    --描述程序集或產(chǎn)品,如果查看可執(zhí)行文件的屬性,這個(gè)值就會(huì)顯示為Comments
      AssemblyProduct     --指定了屬于該程序集的產(chǎn)品名稱
      AssemblyInfomationalVersion    --在引用程序集時(shí),這個(gè)屬性不用于版本檢查,僅用于版本信息,非常適用于指定使用多個(gè)程序集的應(yīng)用程序的版本,打開可執(zhí)行程序的屬性,這個(gè)值就顯示為Product Version
      AssemblyTitle     --是程序集的描述性名稱,可以包括空格,查看屬性時(shí)顯示為Description

      System.Runtime.CompilerServices命名空間中的類:
      AssemblyCulture      --程序集的文化背景,如en-US
      AssemblyDelaySign/AssemblyKeyFile/AssemblyKeyName --用于創(chuàng)建共享程序集的強(qiáng)名
      AssemblyVersion      --指定程序集的版本號,版本問題在共享程序集中具有非常重要的地位
      ======================

      ======================
      跨語言支持
      .NET 使用通用類型系統(tǒng)Common Type System-CTS-定義了如何在.net中定義值類型和引用類型,以及這些類型的內(nèi)存布局
      但CTS沒有確保在任何語言中定義的類型都可以用于其它語言。
      這應(yīng)是公共語言規(guī)范Common Language Specification-CLS 的任務(wù)。
      CLS定義了.net語言必須支持的最低要求
      ======================

      CTS=common type system=通用類型系統(tǒng)
      CLS=common language specification=公共語言規(guī)范
      ======================
      例如:
      **********************************************************************************
      Visual C++編寫的基類HelloMCPP/   繼承于HelloMCPP的類HelloVB/ 繼承于HelloVB的類HelloCSharp
      HelloMCPP   HelloVB    HelloCSharp

      +Hello()    +Hello()    +Hello()
      +Hello2()    +Add()    +Add()
      +Add()       +Main()
      **********************************************************************************
      --使用VS2003創(chuàng)建一個(gè)VC的類-class library(.net)
      1>HelloMCPP
      //HelloMCPP.h
      #pragma once
      #include <stdio.h>
      using namespace System;
      namespace Wrox
      {namespace ProCSharp
      {namespace Assemblies
      {namespace CrossLanguage
      {public _gc class HelloMCPP //_gc 標(biāo)記類HelloMCPP,使類成為一個(gè)托管類
      {public:
         virtual void Hello()
         {Console::WriteLine(S"Hello,ManagedC++");}//S作為字符串的前綴,托管的字符串就會(huì)寫入程序集,并用ldstr推入堆棧
        
         virtual void Hello2()
      ]   {printf("Hello,calling native code \n");}

         int Add(int val1,int val2)
         {return val1+val2;}
      };
      }}}}
      **********************************************************************************
      --使用VS2003創(chuàng)建一個(gè)VB.net的類-class library
      --打開項(xiàng)目屬性,在Root Namespace 中將項(xiàng)目的根命名空間改為Wrox.ProCSharp.Assemblies.CrossLanguage
      ,這樣就改變了類的命名空間
      --添加對HellpMCPP的引用:Project-->Add Reference
      給項(xiàng)目添加引用就是將引用的程序集復(fù)制到VB.net項(xiàng)目的輸出目錄上(/bin),然后對原引用程序集的改變就是獨(dú)立的
      2>HelloVB
      public class HelloVB
         Inherits HelloMCPP

         public Overrides Sub Hello()
          MyBase.Hello() 'MyBase關(guān)鍵字代表基類,此處調(diào)用基類的方法
          Console.WriteLine("Hello,VB.NET")
         End Sub

         public Shadows Function Add(ByVal val1 as integer,_
           ByVal val2 as integer) as integer
          'Shadows關(guān)鍵字用來隱藏基類的方法Add(),因?yàn)樵诨愔蠥dd()不是虛擬(virtual)的
          '不能被重寫
          return val1+val2
         End Function
      End class
      **********************************************************************************
      --創(chuàng)建一個(gè)C#控制臺應(yīng)用程序,添加對HelloVB和HelloMCPP的引用
      3>HelloCSharp
      using System;
      namespace Wrox.ProCSharp.Assemblies.CrossLanguage
      {
         public class HelloCSharp:HelloVB
         {
          public HelloCSharp()
          {}

          public override void Hello()
          {
           base.Hello();
           Console.WriteLine("Hello,C#");
          }

          public new int Add(int val1,int val2)
          {
           return val1+val2;
          }

          [STAThread]

          public static void Main()
          {
           HelloCSharp hello new HelloCSharp();
           hello.Hello();
          }
         }
      }
          
      **********************************************************************************
      最后控制臺應(yīng)用程序的輸出如下:
      Hello,Managed C++
      Hello,VB.NET
      Hello,C#
      *************************
      因?yàn)樗械?net語言都生成MSIL代碼,所有的語言都使用.NET FRAMEWORK中的類,所以在性能上是沒有區(qū)別的
      但仍有一些小的差別,首先,由于語言的不同,某些語言支持的數(shù)據(jù)類型其它語言不支持
      其次,生成的MSIL代碼仍有差別
      在默認(rèn)配置下,VB.NET上的執(zhí)行比較安全,C#上的執(zhí)行比較快,C#也更靈活
      *************************
      在基類中定義的方法在都可以在派生類中調(diào)用,如果方法的參數(shù)是System.UInt32數(shù)據(jù)類型,就不能在VB.NET中使用它
      ,因?yàn)閂B.NET不支持無符號數(shù)據(jù)
      無符號的數(shù)據(jù)類型與CLS不兼容,.net的語言不必支持這種數(shù)據(jù)類型
      **********************************************************************************
      .NET的語言
      .NET consumer工具
         只使用.NET FRAMEWORK中的類,不能創(chuàng)建用于其它語言的.NET類;
         可以使用任何與CLS兼容的類
      .NET extends工具
         可以滿足客戶的要求,可以繼承任何與CLS兼容的.NET類;
         定義了可以由客戶使用的新CLS兼容類
         C++,VB.NET,C#都是.NET extender工具,使用這些語言可以創(chuàng)建CLS兼容類

      **********************************************************************************
      CLSCompliant屬性
      利用它可以把程序集標(biāo)記為與CLS兼容,這樣可以確保這個(gè)程序集中的類能用于所有的.NET consumer工具;
      在公共方法或受保護(hù)的方法中使用與CLS不兼容的數(shù)據(jù)類型時(shí),編譯器會(huì)給出警告;
      在私有方法中使用什么樣的數(shù)據(jù)類型則不重要,因?yàn)樵陬惖耐獠渴褂闷渌Z言時(shí),根本就不能訪問私有方法;
      當(dāng)在公共方法和受保護(hù)的方法中使用與CLS不兼容的類型時(shí),為了讓編譯器發(fā)出警告,可以設(shè)置程序集中的屬性
      CLSCompliant,把這個(gè)屬性添加到AssemblyInfo.cs中:
      [assembly:System.CLSCompliant(true)]
      這樣,在程序集中定義的所有類型和公共方法就都是兼容的,當(dāng)參數(shù)的數(shù)據(jù)類型是不兼容的UINT時(shí),編譯器就會(huì)發(fā)出如下
      警告:error CS3001:Argument type uint is not CLS-compliant
      把程序集標(biāo)記為兼容時(shí),仍可以定義不兼容的方法,如果要重寫某些方法,使其參數(shù)是兼容和不兼容的數(shù)據(jù)類型,就必須把
      類中的不兼容的方法的CLSCompliant屬性設(shè)置為false
      CLSCompliant 屬性可以用到類型,方法,屬性,字段和事件上:
      [CLSCompliant(false)]
      void Method(uint i)
      {//......
      **********************************************************************************
      CLS規(guī)則
      程序集和與CLS兼容的要求:
      方法原形中的所有類型都必須與CLS兼容;
      數(shù)組元素的元素類型必須與CLS兼容。數(shù)組的第一個(gè)元素的下標(biāo)必須是0;
      CLS兼容類必須繼承與CLS兼容類,當(dāng)然,System.Object 是與CLS兼容的;
      在CLS兼容類中,方法名士不區(qū)分大小寫的,兩個(gè)方法不能僅根據(jù)其名稱中字母的大小寫來區(qū)分;
      枚舉的類型必須是Int16,Int32,Int64,其它類型的枚舉都是不兼容的;
      上述要求只適用于公共成員和受保護(hù)的成員,私有方法則無需考慮這些要求,它們可以使用不兼容的類型,
      而程序集仍然是兼容的
      還應(yīng)該遵循更一般的命名約定
      C# VB.NET 更一般
      int integer Int32
      long long Int64
      float single Single
      在利用CLS規(guī)范和規(guī)則進(jìn)行編譯時(shí),很容易創(chuàng)建出可以用于多種語言的組件,不需要使用所有的.NET FrameWork語言來測試該組件
      **********************************************************************************
      全局程序集緩存 Global Assembly Cache
      可全局使用的程序集的緩存
      大多數(shù)共享程序集都安裝在這個(gè)緩存中,其中也安裝了一些私有程序集
      如果私有程序集使用本機(jī)圖像生成器編譯為本機(jī)代碼,編譯好的本機(jī)代碼也會(huì)存儲(chǔ)在這個(gè)緩存中
      **********************************************************************************
      本機(jī)圖像生成器 native image generator Ngen.exe
      可以在安裝期間把IL代碼編譯為本機(jī)代碼,這樣程序啟動(dòng)就比較快,因?yàn)椴辉傩枰谶\(yùn)行時(shí)進(jìn)行編譯
      Ngen工具在本機(jī)圖像緩存中安裝本機(jī)圖像,本機(jī)圖像緩存是全局程序集緩存的一部分

      **********************************************************************************
      全局程序集緩存查看器
      全局程序緩存可以使用shfusion.dll來顯示,它是一個(gè)Windows外殼擴(kuò)展程序,可以查看和處理緩存的內(nèi)容
      Windows外殼擴(kuò)展程序是一個(gè)與Windows資源管理器集成的COM DLL
      用戶啟動(dòng)資源管理器,進(jìn)入<windir>/assembly目錄即可
      可以查看全局程序集的名稱,類型,版本,文化和公鑰標(biāo)記,通過查看全局程序集的類型可以確定程序集是否
      是使用本機(jī)圖像生成器安裝的
      在該目錄下,有GAC和NativeImages_<runtime version>目錄,分別是共享程序集的目錄和編譯為本機(jī)代碼的程序集

      **********************************************************************************
      全局程序集緩存工具 gacutil.exe
      全局程序集緩存查看器可以查看和刪除程序集,但不能在腳本代碼中使用該工具,例如創(chuàng)建安裝程序。
      gacutil.exe 可以使用命令行安裝,卸載和顯示程序集
      選項(xiàng): gacutil /l   --顯示程序集緩存中的所有程序集
         gacutil /i mydll --把共享程序集mydll安裝到程序集緩存上
         gacutil /u mydll --卸載程序集mydll
         gacutil /ungen mydll --從本機(jī)圖像緩存中卸載程序集
      **********************************************************************************
      創(chuàng)建共享程序集
      程序集可以由一個(gè)應(yīng)用程序使用,在默認(rèn)下部共享程序集,在使用私有程序集時(shí),不需要考慮共享時(shí)需要考慮的任何要求
      共享程序集名:必須是全局唯一的,1要保護(hù)該名稱,2要使得其他人不能使用這個(gè)名稱創(chuàng)建程序集
         COM使用全局唯一標(biāo)識符GUID只解決了第一個(gè)問題,第二個(gè)問題仍然沒有解決,每個(gè)人
      都可以盜用這個(gè)GUID,用相同的標(biāo)識符創(chuàng)建不同的對象
         這兩個(gè)問題使用.NET程序集的強(qiáng)名都可以解決
         強(qiáng)名由以下項(xiàng)目組成:
           程序集本身的名稱
           版本號
           公鑰,保證強(qiáng)名是獨(dú)一無二的,并且保證引用的程序集不能被另一個(gè)源替代
           文化
      共享程序集必須有一個(gè)強(qiáng)名,來唯一的標(biāo)識該程序集
      每個(gè)程序集不能有新的公鑰,但可以在公司中有這樣一個(gè)公鑰,這樣該密鑰就唯一的標(biāo)識了公司的程序集
      但是 ,這個(gè)密鑰不能用作信任密鑰,程序集可以利用Authenticode簽名來建立信任關(guān)系,
      Authenticode中的密鑰可以與強(qiáng)名中使用的密鑰不同

      **********************************************************************************
      公鑰的加密
      對稱加密:使用同一個(gè)密鑰進(jìn)行加密和解密
      公鑰/私鑰加密:使用一個(gè)公鑰加密,使用對應(yīng)的私鑰解密/使用一個(gè)私鑰加密,使用對應(yīng)的公鑰解密
          成對創(chuàng)建公鑰和私鑰,公鑰可以任何人使用,甚至可以放在web站點(diǎn)上,但私鑰必須安全的加鎖
      Sarah-->one email -->Julian,除了Julian外的人都不能看
      使用Julian的公鑰加密,Julian打開該email,并使用他秘密存儲(chǔ)的私鑰解密
      但還有一個(gè)問題,Julian不能確保email是Sarah發(fā)來的,任何人都可以使用Julian的公鑰加密發(fā)送email給他
      解決辦法是黨Sarah發(fā)送email給Julian時(shí),使用Julian的公鑰加密郵件之前他添加了自己的簽名,再使用自己的
      私鑰加密該簽名,然后使用Julian的公鑰加密email,這個(gè)簽名可以使用Sarah的公鑰來解密,而Julian可以
      訪問Sarah的公鑰,在解密了簽名后,Julian就可以確定是Sarah發(fā)送了email

      **********************************************************************************
      將公鑰/私鑰應(yīng)用于程序集
      創(chuàng)建共享組件,必須使用公鑰/私鑰對
      編譯器把公鑰寫入程序集清單,創(chuàng)建屬于該程序集的所有文件的散列表--用私鑰標(biāo)記這個(gè)散列表
      私鑰不存儲(chǔ)在程序集中,確保沒有人可以修改這個(gè)程序集,簽名可以使用公鑰來驗(yàn)證
      在開發(fā)過程中,客戶程序集必須引用 共享程序集。編譯器把引用程序集的公鑰寫入客戶程序集的清單中
      要減少存儲(chǔ)量,就不應(yīng)把公鑰寫入客戶程序集的清單,而應(yīng)寫入公鑰標(biāo)記,公鑰標(biāo)記是公鑰散列表中的最后8位字節(jié),且是唯一的
      在運(yùn)行期間加載共享程序集時(shí)(如果客戶程序集是使用本機(jī)圖像生成器安裝的,則應(yīng)在安裝期間加載),
      共享程序集的散列表可以使用存儲(chǔ)在客戶程序集中的公鑰來驗(yàn)證,除了私鑰的主人外其他人都不能修改共享程序集
      例如:
      銷售商A創(chuàng)建了一個(gè)組件Math,在客戶機(jī)上引用該組件,黑客的組件就無法替代它,只有私鑰的主人才能用
      新版本來替換原來的共享組件,保證了其完整性

      **********************************************************************************
      創(chuàng)建共享程序集
      例子
      1 建立一個(gè)Visual C# Class Library 項(xiàng)目 SharedDemo,把命名空間改為Wrox.ProCSharp.Assemblies.Sharing
           類名改為SimpleShared
      using System;
      using System.Collection.Specialized;
      using System.IO;

      namespace Wrox.ProCSharp.Assemblies.Sharing
      {
         public class SharedDemo
         {
          private StringCollection quotes;//類的構(gòu)造函數(shù)將文件的所有行都讀到其中
             //文件名作為參數(shù)傳遞到構(gòu)造函數(shù)
          private Random random;
         
          public SharedDemo(string filename)
          {
           quotes = new StringCollection();
           Stream stream =File.OpenFile(filename);
           StreamReader streamReader = new StreamReader(stream);
           string quote;
          
           while((quote=streamReader.ReadLine())!=null)
           {
            quotes.Add(quote);
           }
           streamReader.Close();
           stream.Close();
           random = new Random();
          }
          public string GetQuoteOfTheDay()
          //返回這個(gè)集合的一個(gè)隨機(jī)字符串
          {
           int index = random.Next(1,quotes.Count);
           retrun quotes[index];
          }
         }
      }
      *************************
      * a>創(chuàng)建強(qiáng)名稱 *--程序集中有了公鑰
      *************************
         要共享這個(gè)組件,需要一個(gè)強(qiáng)名稱,要?jiǎng)?chuàng)建這個(gè)名稱可以使用強(qiáng)名稱工具sn:
         sn -k mykey.snk
      強(qiáng)名稱工具生成和編寫一個(gè)公鑰/私鑰對,并把該密鑰對寫到文件中,此處的文件是mykey.snk,現(xiàn)在可以
      在向?qū)傻奈募嗀ssemblyinfo.cs中設(shè)置屬性AssemblyKeyFile,該屬性可以設(shè)置為密鑰文件的絕對路徑,也可以
      設(shè)置為密鑰文件的相對路徑%ProjectDirectory\obj\<configuration>目錄,所以../../mykey.snk引用項(xiàng)目目錄中的
      一個(gè)密鑰,在開始建立一個(gè)項(xiàng)目時(shí),該密鑰安裝到Crypto Service Provider(CSP)中,如果該密鑰已經(jīng)安裝到CSP中,就可以
      使用AssemblyKeyName屬性
      下面是對Assemblyinfo.cs的修改
      [assembly:AssemblyDelaySign(false)]
      [assembly:AssemblyKeyFile("../../mykey.snk")]
      [assembly:AssemblyKeyName("")]
      在重新建立該文件后,使用ildasm查看該程序集,則該程序集的清單中應(yīng)有一個(gè)公鑰

      *************************
      * b>安裝共享程序集 *
      *************************
      使用全局程序集緩存工具gacutil及其/I選項(xiàng)把它安裝到全局程序集緩存中:
      gacutil /i SharedDemo.dll
      可以使用全局程序集緩存查看器檢查共享程序集的版本,看看它是否安裝成功

      *************************
      * c>使用共享程序集 *
      *************************
      創(chuàng)建一個(gè)C#控制臺應(yīng)用程序Client,不是把新項(xiàng)目添加到原來的解決方案中,而是創(chuàng)建一個(gè)新的解決方案
      這樣在重新建立客戶時(shí),就不會(huì)重新建立該共享程序集了。
      以引用私有程序集方式引用程序集SimpleShared.dll,使用菜單Project|Add Reference
      有了共享程序集,引用屬性CopyLocal就可以設(shè)置為false,這樣,共享程序集就不會(huì)復(fù)制到輸出文件的目錄下
      而會(huì)從全局程序集緩存中加載
      下面是客戶機(jī)應(yīng)用程序的代碼:
      using System;
      namespace Wrox.ProCSharp.Assemblies.Sharing
      {
         class Client
         {
          [STAThread]
          static void Main(string[] args)
          {
           SharedDemo quotes = new SharedDemo(@"C:\ProCSharp\Assemblies\Quotes.txt");
           for(int i=0;i<3;i++)
           {
            Console.WriteLine(quotes.GetQuoteOfTheDay());
            Console.WriteLine();
           }
          }
         }
      }
      **********************************************************************************
      公鑰的標(biāo)記也可以使用強(qiáng)名稱工具sn在共享程序集中查看:sn -T會(huì)顯示程序集中的公鑰標(biāo)記
      sn -Tp顯示標(biāo)記和公鑰
      **********************************************************************************
      程序集的延遲簽名
      公司的私鑰應(yīng)安全存儲(chǔ),大多數(shù)公司不允許所有的開發(fā)人員訪問私鑰,只有幾個(gè)有安全權(quán)限的人才能訪問
      這就是程序集的簽名可以以后(例如發(fā)布前)添加的原因
      全局程序集屬性AssemblyDelaySign設(shè)置為true時(shí),簽名就不會(huì)存儲(chǔ)在程序集中,但保留了足夠的空間,以便
      以后添加。
      但是不使用密鑰就不能測試程序集,在全局程序集緩存中安裝它
      但可以使用臨時(shí)密鑰進(jìn)行測試,以后再用真正的密鑰代替這個(gè)臨時(shí)密鑰
      程序集的延時(shí)簽名需要執(zhí)行以下步驟:
      1>使用sn創(chuàng)建一個(gè)公鑰/私鑰對,生成文件mykey.snk,包含公鑰和私.snsn -k mykey.snk
      2>提取公鑰,使之可以用于開發(fā)人員。選項(xiàng)-p提取密鑰文件的公鑰,文件mypublickey.snk僅包含公鑰
         sn -p mykey.snk mypublickey.snk
      公司中所有開發(fā)人員都可以使用這個(gè)密鑰文件mypublickey.snk
      在文件AssemblyInfo.cs中設(shè)置AssemblyDelaySign和AssemblyKeyFile屬性
      [assembly:AssemblyDelaySign(true)]
      [assembly:AssemblyKeyFile("../../mypublickey.snk")]
      3>關(guān)閉簽名的驗(yàn)證功能,因?yàn)槌绦蚣瘺]有包含簽名
      sn -Vr ShareDemo.dll
      4>在發(fā)布之前,程序集可以用sn工具重新簽名
      -R選項(xiàng)用于對以前已簽名或延遲簽名的程序集進(jìn)行重新簽名
      sn -R MyAssembly.dll mykey.snk
      注意:簽名的驗(yàn)證功能只能在開發(fā)過程中關(guān)閉,不經(jīng)過驗(yàn)證是不能發(fā)布程序集的,因?yàn)檫@個(gè)程序集可能被懷有惡意的程序集代替
      **********************************************************************************

      程序集(assembly)是包含編譯好的、面向.NET Framework的代碼的邏輯單元。程序集是完全自我描述性的,也是一個(gè)邏輯單元而不是物理單元,它可以存儲(chǔ)在多個(gè)文件中(動(dòng)態(tài)程序集的確存儲(chǔ)在內(nèi)存中,而不是存儲(chǔ)在文件中)。如果一個(gè)程序集存儲(chǔ)在多個(gè)文件中,其中就會(huì)有一個(gè)包含入口點(diǎn)的主文件,該文件描述了程序集中的其他文件。

      注意可執(zhí)行代碼和庫代碼使用相同的程序集結(jié)構(gòu)。惟一的區(qū)別是可執(zhí)行的程序集包含一個(gè)主程序入口點(diǎn),而庫程序集則不包含。

      程序集的一個(gè)重要特性是它們包含的元數(shù)據(jù)描述了對應(yīng)代碼中定義的類型和方法。程序集也包含描述程序集本身的元數(shù)據(jù),這種程序集元數(shù)據(jù)包含在一個(gè)稱為程序集清單的區(qū)域中,可以檢查程序集的版本及其完整性。

      注意:

      ildasm是一個(gè)基于Windows的實(shí)用程序,可以用于檢查程序集的內(nèi)容,包括程序集清單和元數(shù)據(jù)。第15章將介紹ildasm。

      程序集包含程序的元數(shù)據(jù),表示調(diào)用給定程序集中的代碼的應(yīng)用程序或其他程序集不需要指定注冊表或其他數(shù)據(jù)源,以便確定如何使用該程序集。這與以前的COM有很大的不同,以前,組件的GUID和接口必須從注冊表中獲取,在某些情況下,方法和屬性的詳細(xì)信息也需要從類型庫中讀取。

      把數(shù)據(jù)分散在3個(gè)以上的不同位置上,可能會(huì)出現(xiàn)信息不同步的情況,從而妨礙其他軟件成功地使用該組件。有了程序集后,就不會(huì)發(fā)生這種情況,因?yàn)樗械脑獢?shù)據(jù)都與程序的可執(zhí)行指令存儲(chǔ)在一起。注意,即使程序集存儲(chǔ)在幾個(gè)文件中,數(shù)據(jù)也不會(huì)出現(xiàn)不同步的問題。這是因?yàn)榘绦蚣肟诘奈募泊鎯?chǔ)了其他文件的細(xì)節(jié)、散列和內(nèi)容,如果一個(gè)文件被替換,或者被塞滿,系統(tǒng)肯定會(huì)檢測出來,并拒絕加載程序集。

      程序集有兩種類型:共享程序集和私有程序集。

      1.4.1 私有程序集

      私有程序集是最簡單的一種程序集類型。私有程序集一般附帶在某些軟件上,且只能用于該軟件中。附帶私有程序集的常見情況是,以可執(zhí)行文件或許多庫的方式提供應(yīng)用程序,這些庫包含的代碼只能用于該應(yīng)用程序。

      系統(tǒng)可以保證私有程序集不被其他軟件使用,因?yàn)閼?yīng)用程序只能加載位于主執(zhí)行文件所在文件夾或其子文件夾中的程序集。

      用戶一般會(huì)希望把商用軟件安裝在它自己的目錄下,這樣軟件包沒有覆蓋、修改或加載另一個(gè)軟件包的私有程序集的風(fēng)險(xiǎn)。私有程序集只能用于自己的軟件包,這樣,用戶對什么軟件使用它們就有了更多的控制。因此,不需要采取安全措施,因?yàn)檫@沒有其他商用軟件用某個(gè)新版本的程序集覆蓋原來的私有程序集的風(fēng)險(xiǎn)(但軟件是專門執(zhí)行懷有惡意的損害性操作的情況除外)。名稱也不會(huì)有沖突。如果私有程序集中的類正巧與另一個(gè)人的私有程序集中的類同名,是不會(huì)有問題的,因?yàn)榻o定的應(yīng)用程序只能使用私有程序集的名稱。

      因?yàn)樗接谐绦蚣耆亲院降?,所以安裝它的過程就很簡單。只需把相應(yīng)的文件放在文件系統(tǒng)的對應(yīng)文件夾中即可(不需要注冊表項(xiàng)),這個(gè)過程稱為“0影響(xcopy)安裝”。

      1.4.2 共享程序集

      共享程序集是其他應(yīng)用程序可以使用的公共庫。因?yàn)槠渌浖梢栽L問共享程序集,所以需要采取一定的保護(hù)措施來防止以下風(fēng)險(xiǎn):

             名稱沖突,另一個(gè)公司的共享程序集執(zhí)行的類型與自己的共享程序集中的類型同名。因?yàn)榭蛻魴C(jī)代碼理論上可以同時(shí)訪問這些程序集,所以這是一個(gè)嚴(yán)重的問題。

             程序集被同一個(gè)程序集的不同版本覆蓋——新版本與某些已有的客戶機(jī)代碼不兼容。

      這些問題的解決方法是把共享程序集放在文件系統(tǒng)的一個(gè)特定的子目錄樹中,稱為全局程序集高速緩存(GAC)。與私有程序集不同,不能簡單地把共享程序集復(fù)制到對應(yīng)的文件夾中,而需要專門安裝到高速緩存中,這個(gè)過程可以用許多.NET工具來完成,其中包含對程序集的檢查、在程序集高速緩存中設(shè)置一個(gè)小的文件夾層次結(jié)構(gòu),以確保程序集的完整性。

      為了避免名稱沖突,共享程序集應(yīng)根據(jù)私有密鑰加密法指定一個(gè)名稱(私有程序集只需要指定與其主文件名相同的名稱即可)。該名稱稱為強(qiáng)名(strong name),并保證其惟一性,它必須由要引用共享程序集的應(yīng)用程序來引用。

      與覆蓋程序集相關(guān)的問題,可以通過在程序集清單中指定版本信息來解決,也可以通過同時(shí)安裝來解決。

      1.4.3 反射

      因?yàn)槌绦蚣鎯?chǔ)了元數(shù)據(jù),包括在程序集中定義的所有類型和這些類型的成員的細(xì)節(jié),所以可以編程訪問這些元數(shù)據(jù)。這個(gè)技術(shù)稱為反射,第11章詳細(xì)介紹了它們。該技術(shù)很有趣,因?yàn)樗硎就泄艽a實(shí)際上可以檢查其他托管代碼,甚至檢查它自己,以確定該代碼的信息。它們常常用于獲取特性的詳細(xì)信息,也可以把反射用于其他目的,例如作為實(shí)例化類或調(diào)用方法的一種間接方式,如果把方法上的類名指定為字符串,就可以選擇類來實(shí)例化方法,以便在運(yùn)行時(shí)調(diào)用,而不是在編譯時(shí)調(diào)用,例如根據(jù)用戶的輸入來調(diào)用(動(dòng)態(tài)綁定)。


        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多