小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

C#程序集(assembly)(精)

 悟靜 2012-05-02

程序集

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

------------------------------------------
======================
進(jìn)程〉應(yīng)用程序域〉程序集〉對(duì)象
======================
------------------------------------------
應(yīng)用程序域之間可以通信,或使用代理
AppDomain類(lèi)用于創(chuàng)建和中斷應(yīng)用程序域,加載和卸載程序集和類(lèi),枚舉域中的程序集和線(xiàn)程
例如: 1--創(chuàng)建一個(gè)控制臺(tái)應(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類(lèi)的實(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類(lèi)的FriendlyName屬性顯示當(dāng)前域的名稱(chēng)

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

     secondDomain.ExecuteAssembly("AssemblyA.exe");
     //把程序集AssemblyA加載到新域中,通過(guò)調(diào)用ExecuteAssembly來(lái)調(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í)例化的類(lèi);3-true表示不區(qū)分大小寫(xiě);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)用程序域只能通過(guò)中斷應(yīng)用程序域來(lái)進(jìn)行


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

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

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

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

FILE-->OPEN-->打開(kāi)程序集
======================
======================
構(gòu)建程序集
1-可以創(chuàng)建模塊:csc /target:module hello.cs 模塊是一個(gè)沒(méi)有程序集特性的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)椴⒉皇撬蓄?lèi)都在一個(gè)文件中
   模塊只在需要時(shí)加載
2是是否需要使用多種編程語(yǔ)言來(lái)創(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命名空間中的類(lèi):
AssemblyCompany     ---指定公司名
AssemblyConfiguration    --指定建立信息,例如零售或調(diào)試信息
AssemblyCopyright/Assembly Trademark --包含版權(quán)和商標(biāo)信息
AssemblyDefaultAlias    --如果程序集名稱(chēng)不容易理解,如動(dòng)態(tài)創(chuàng)建程序集名稱(chēng)時(shí)的GUID,就可以使用該屬性,指定一個(gè)別名
AssemblyDescription    --描述程序集或產(chǎn)品,如果查看可執(zhí)行文件的屬性,這個(gè)值就會(huì)顯示為Comments
AssemblyProduct     --指定了屬于該程序集的產(chǎn)品名稱(chēng)
AssemblyInfomationalVersion    --在引用程序集時(shí),這個(gè)屬性不用于版本檢查,僅用于版本信息,非常適用于指定使用多個(gè)程序集的應(yīng)用程序的版本,打開(kāi)可執(zhí)行程序的屬性,這個(gè)值就顯示為Product Version
AssemblyTitle     --是程序集的描述性名稱(chēng),可以包括空格,查看屬性時(shí)顯示為Description

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

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

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

+Hello()    +Hello()    +Hello()
+Hello2()    +Add()    +Add()
+Add()       +Main()
**********************************************************************************
--使用VS2003創(chuàng)建一個(gè)VC的類(lèi)-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)記類(lèi)HelloMCPP,使類(lèi)成為一個(gè)托管類(lèi)
{public:
   virtual void Hello()
   {Console::WriteLine(S"Hello,ManagedC++");}//S作為字符串的前綴,托管的字符串就會(huì)寫(xiě)入程序集,并用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的類(lèi)-class library
--打開(kāi)項(xiàng)目屬性,在Root Namespace 中將項(xiàng)目的根命名空間改為Wrox.ProCSharp.Assemblies.CrossLanguage
,這樣就改變了類(lèi)的命名空間
--添加對(duì)HellpMCPP的引用:Project-->Add Reference
給項(xiàng)目添加引用就是將引用的程序集復(fù)制到VB.net項(xiàng)目的輸出目錄上(/bin),然后對(duì)原引用程序集的改變就是獨(dú)立的
2>HelloVB
public class HelloVB
   Inherits HelloMCPP

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

   public Shadows Function Add(ByVal val1 as integer,_
     ByVal val2 as integer) as integer
    'Shadows關(guān)鍵字用來(lái)隱藏基類(lèi)的方法Add(),因?yàn)樵诨?lèi)中Add()不是虛擬(virtual)的
    '不能被重寫(xiě)
    return val1+val2
   End Function
End class
**********************************************************************************
--創(chuàng)建一個(gè)C#控制臺(tái)應(yīng)用程序,添加對(duì)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();
    }
   }
}
    
**********************************************************************************
最后控制臺(tái)應(yīng)用程序的輸出如下:
Hello,Managed C++
Hello,VB.NET
Hello,C#
*************************
因?yàn)樗械?net語(yǔ)言都生成MSIL代碼,所有的語(yǔ)言都使用.NET FRAMEWORK中的類(lèi),所以在性能上是沒(méi)有區(qū)別的
但仍有一些小的差別,首先,由于語(yǔ)言的不同,某些語(yǔ)言支持的數(shù)據(jù)類(lèi)型其它語(yǔ)言不支持
其次,生成的MSIL代碼仍有差別
在默認(rèn)配置下,VB.NET上的執(zhí)行比較安全,C#上的執(zhí)行比較快,C#也更靈活
*************************
在基類(lèi)中定義的方法在都可以在派生類(lèi)中調(diào)用,如果方法的參數(shù)是System.UInt32數(shù)據(jù)類(lèi)型,就不能在VB.NET中使用它
,因?yàn)閂B.NET不支持無(wú)符號(hào)數(shù)據(jù)
無(wú)符號(hào)的數(shù)據(jù)類(lèi)型與CLS不兼容,.net的語(yǔ)言不必支持這種數(shù)據(jù)類(lèi)型
**********************************************************************************
.NET的語(yǔ)言
.NET consumer工具
   只使用.NET FRAMEWORK中的類(lèi),不能創(chuàng)建用于其它語(yǔ)言的.NET類(lèi);
   可以使用任何與CLS兼容的類(lèi)
.NET extends工具
   可以滿(mǎn)足客戶(hù)的要求,可以繼承任何與CLS兼容的.NET類(lèi);
   定義了可以由客戶(hù)使用的新CLS兼容類(lèi)
   C++,VB.NET,C#都是.NET extender工具,使用這些語(yǔ)言可以創(chuàng)建CLS兼容類(lèi)

**********************************************************************************
CLSCompliant屬性
利用它可以把程序集標(biāo)記為與CLS兼容,這樣可以確保這個(gè)程序集中的類(lèi)能用于所有的.NET consumer工具;
在公共方法或受保護(hù)的方法中使用與CLS不兼容的數(shù)據(jù)類(lèi)型時(shí),編譯器會(huì)給出警告;
在私有方法中使用什么樣的數(shù)據(jù)類(lèi)型則不重要,因?yàn)樵陬?lèi)的外部使用其它語(yǔ)言時(shí),根本就不能訪(fǎng)問(wèn)私有方法;
當(dāng)在公共方法和受保護(hù)的方法中使用與CLS不兼容的類(lèi)型時(shí),為了讓編譯器發(fā)出警告,可以設(shè)置程序集中的屬性
CLSCompliant,把這個(gè)屬性添加到AssemblyInfo.cs中:
[assembly:System.CLSCompliant(true)]
這樣,在程序集中定義的所有類(lèi)型和公共方法就都是兼容的,當(dāng)參數(shù)的數(shù)據(jù)類(lèi)型是不兼容的UINT時(shí),編譯器就會(huì)發(fā)出如下
警告:error CS3001:Argument type uint is not CLS-compliant
把程序集標(biāo)記為兼容時(shí),仍可以定義不兼容的方法,如果要重寫(xiě)某些方法,使其參數(shù)是兼容和不兼容的數(shù)據(jù)類(lèi)型,就必須把
類(lèi)中的不兼容的方法的CLSCompliant屬性設(shè)置為false
CLSCompliant 屬性可以用到類(lèi)型,方法,屬性,字段和事件上:
[CLSCompliant(false)]
void Method(uint i)
{//......
**********************************************************************************
CLS規(guī)則
程序集和與CLS兼容的要求:
方法原形中的所有類(lèi)型都必須與CLS兼容;
數(shù)組元素的元素類(lèi)型必須與CLS兼容。數(shù)組的第一個(gè)元素的下標(biāo)必須是0;
CLS兼容類(lèi)必須繼承與CLS兼容類(lèi),當(dāng)然,System.Object 是與CLS兼容的;
在CLS兼容類(lèi)中,方法名士不區(qū)分大小寫(xiě)的,兩個(gè)方法不能僅根據(jù)其名稱(chēng)中字母的大小寫(xiě)來(lái)區(qū)分;
枚舉的類(lèi)型必須是Int16,Int32,Int64,其它類(lèi)型的枚舉都是不兼容的;
上述要求只適用于公共成員和受保護(hù)的成員,私有方法則無(wú)需考慮這些要求,它們可以使用不兼容的類(lèi)型,
而程序集仍然是兼容的
還應(yīng)該遵循更一般的命名約定
C# VB.NET 更一般
int integer Int32
long long Int64
float single Single
在利用CLS規(guī)范和規(guī)則進(jìn)行編譯時(shí),很容易創(chuàng)建出可以用于多種語(yǔ)言的組件,不需要使用所有的.NET FrameWork語(yǔ)言來(lái)測(cè)試該組件
**********************************************************************************
全局程序集緩存 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來(lái)顯示,它是一個(gè)Windows外殼擴(kuò)展程序,可以查看和處理緩存的內(nèi)容
Windows外殼擴(kuò)展程序是一個(gè)與Windows資源管理器集成的COM DLL
用戶(hù)啟動(dòng)資源管理器,進(jìn)入<windir>/assembly目錄即可
可以查看全局程序集的名稱(chēng),類(lèi)型,版本,文化和公鑰標(biāo)記,通過(guò)查看全局程序集的類(lèi)型可以確定程序集是否
是使用本機(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ù)該名稱(chēng),2要使得其他人不能使用這個(gè)名稱(chēng)創(chuàng)建程序集
   COM使用全局唯一標(biāo)識(shí)符GUID只解決了第一個(gè)問(wèn)題,第二個(gè)問(wèn)題仍然沒(méi)有解決,每個(gè)人
都可以盜用這個(gè)GUID,用相同的標(biāo)識(shí)符創(chuàng)建不同的對(duì)象
   這兩個(gè)問(wèn)題使用.NET程序集的強(qiáng)名都可以解決
   強(qiáng)名由以下項(xiàng)目組成:
     程序集本身的名稱(chēng)
     版本號(hào)
     公鑰,保證強(qiáng)名是獨(dú)一無(wú)二的,并且保證引用的程序集不能被另一個(gè)源替代
     文化
共享程序集必須有一個(gè)強(qiáng)名,來(lái)唯一的標(biāo)識(shí)該程序集
每個(gè)程序集不能有新的公鑰,但可以在公司中有這樣一個(gè)公鑰,這樣該密鑰就唯一的標(biāo)識(shí)了公司的程序集
但是 ,這個(gè)密鑰不能用作信任密鑰,程序集可以利用Authenticode簽名來(lái)建立信任關(guān)系,
Authenticode中的密鑰可以與強(qiáng)名中使用的密鑰不同

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

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

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

namespace Wrox.ProCSharp.Assemblies.Sharing
{
   public class SharedDemo
   {
    private StringCollection quotes;//類(lèi)的構(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)名稱(chēng) *--程序集中有了公鑰
*************************
   要共享這個(gè)組件,需要一個(gè)強(qiáng)名稱(chēng),要?jiǎng)?chuàng)建這個(gè)名稱(chēng)可以使用強(qiáng)名稱(chēng)工具sn:
   sn -k mykey.snk
強(qiáng)名稱(chēng)工具生成和編寫(xiě)一個(gè)公鑰/私鑰對(duì),并把該密鑰對(duì)寫(xiě)到文件中,此處的文件是mykey.snk,現(xiàn)在可以
在向?qū)傻奈募嗀ssemblyinfo.cs中設(shè)置屬性AssemblyKeyFile,該屬性可以設(shè)置為密鑰文件的絕對(duì)路徑,也可以
設(shè)置為密鑰文件的相對(duì)路徑%ProjectDirectory\obj\<configuration>目錄,所以../../mykey.snk引用項(xiàng)目目錄中的
一個(gè)密鑰,在開(kāi)始建立一個(gè)項(xiàng)目時(shí),該密鑰安裝到Crypto Service Provider(CSP)中,如果該密鑰已經(jīng)安裝到CSP中,就可以
使用AssemblyKeyName屬性
下面是對(duì)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#控制臺(tái)應(yīng)用程序Client,不是把新項(xiàng)目添加到原來(lái)的解決方案中,而是創(chuàng)建一個(gè)新的解決方案
這樣在重新建立客戶(hù)時(shí),就不會(huì)重新建立該共享程序集了。
以引用私有程序集方式引用程序集SimpleShared.dll,使用菜單Project|Add Reference
有了共享程序集,引用屬性CopyLocal就可以設(shè)置為false,這樣,共享程序集就不會(huì)復(fù)制到輸出文件的目錄下
而會(huì)從全局程序集緩存中加載
下面是客戶(hù)機(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)名稱(chēng)工具sn在共享程序集中查看:sn -T會(huì)顯示程序集中的公鑰標(biāo)記
sn -Tp顯示標(biāo)記和公鑰
**********************************************************************************
程序集的延遲簽名
公司的私鑰應(yīng)安全存儲(chǔ),大多數(shù)公司不允許所有的開(kāi)發(fā)人員訪(fǎng)問(wèn)私鑰,只有幾個(gè)有安全權(quán)限的人才能訪(fǎng)問(wèn)
這就是程序集的簽名可以以后(例如發(fā)布前)添加的原因
全局程序集屬性AssemblyDelaySign設(shè)置為true時(shí),簽名就不會(huì)存儲(chǔ)在程序集中,但保留了足夠的空間,以便
以后添加。
但是不使用密鑰就不能測(cè)試程序集,在全局程序集緩存中安裝它
但可以使用臨時(shí)密鑰進(jìn)行測(cè)試,以后再用真正的密鑰代替這個(gè)臨時(shí)密鑰
程序集的延時(shí)簽名需要執(zhí)行以下步驟:
1>使用sn創(chuàng)建一個(gè)公鑰/私鑰對(duì),生成文件mykey.snk,包含公鑰和私.snsn -k mykey.snk
2>提取公鑰,使之可以用于開(kāi)發(fā)人員。選項(xiàng)-p提取密鑰文件的公鑰,文件mypublickey.snk僅包含公鑰
   sn -p mykey.snk mypublickey.snk
公司中所有開(kāi)發(fā)人員都可以使用這個(gè)密鑰文件mypublickey.snk
在文件AssemblyInfo.cs中設(shè)置AssemblyDelaySign和AssemblyKeyFile屬性
[assembly:AssemblyDelaySign(true)]
[assembly:AssemblyKeyFile("../../mypublickey.snk")]
3>關(guān)閉簽名的驗(yàn)證功能,因?yàn)槌绦蚣瘺](méi)有包含簽名
sn -Vr ShareDemo.dll
4>在發(fā)布之前,程序集可以用sn工具重新簽名
-R選項(xiàng)用于對(duì)以前已簽名或延遲簽名的程序集進(jìn)行重新簽名
sn -R MyAssembly.dll mykey.snk
注意:簽名的驗(yàn)證功能只能在開(kāi)發(fā)過(guò)程中關(guān)閉,不經(jīng)過(guò)驗(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í)行代碼和庫(kù)代碼使用相同的程序集結(jié)構(gòu)。惟一的區(qū)別是可執(zhí)行的程序集包含一個(gè)主程序入口點(diǎn),而庫(kù)程序集則不包含。

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

注意:

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

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

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

程序集有兩種類(lèi)型:共享程序集和私有程序集。

1.4.1 私有程序集

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

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

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

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

1.4.2 共享程序集

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

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

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

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

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

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

1.4.3 反射

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


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

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多