.NET組件 vs. COM組件

寫在前面:我沒有開發過COM組件的經驗,只是在作文獻綜述的時候須要瞭解這方面的知識,因此若是哪裏說錯了或者是我理解錯了,還但願你們能夠指出,謝謝。我不是程序員也不是計算機專業,只是課題偏了這個方向,所以不少基礎概念或許有理解錯,真心但願能夠獲得你們的指正,再次感謝。程序員


COM object以接口的方式向客戶端提供服務。一個COM component能夠包含多個COM object,一個COM object能夠有多個接口,其關係如圖1所示。安全

圖1 COM組件、COM對象和接口關係app

在Windows OS上,COM組件以.dll或者.exe的文件形式存在。其中.dll是進程內組件(in-process component),.exe是進程外組件(out-process component)。進程內組件意味着該組件會被加載到客戶端所在的進程中,而進程外組件則意味着該組件會被加載到一個新的進程中。dom

二進制接口是COM組件中的重要概念,正是由於存在binary interface compatibility, 組件的開發語言不受限制,不必定非得是C/C++。接口是用Microsoft Interface Definition Language (MIDL)描述的。每一個接口有惟一標識,使用IID(interface identifier)命名。接口都須要繼承自IUnknown接口,該接口提供了對接口的生存期控制和接口查詢。下面是一個用MIDL描述的接口的例子:ide

interface IWithdraw : IUnknown
{
    HRESULT Withdraw([in] Bank bank, [in] Integer amount, [out, retval] int* balance);
};

每一個COM object也有一個惟一標識,用CLSID表示。客戶端經過COM庫和類廠成功建立了對象的實例後,會獲得一個指向COM object某個接口的指針(pointer),該指針實際上又指向了另外一個指針(interface pointer),第二個指針指向一組函數,稱爲接口函數表或虛函數表(virtual table pointer),如圖2所示。函數

圖2 接口結構spa

COM component使用前須要先註冊。組件程序把它所實現的COM object的信息以及接口信息都保存在註冊表中,而後COM庫經過系統註冊表所提供的信息進行組件的建立工做。操作系統

在組件的建立工做中,還須要用到類廠(class factory)。類廠自己也是一個COM object,它支持一個特殊的接口IClassFactory,其定義以下:指針

class IClassFactory : public IUnknown
{
    virtual HRESULT_stdcall CreateInstance(IUnknown *pUnknownOuter, const IID&iid, void**ppv) = 0;
    virtual HRESULT_stdcall LockServer(BOOL bLock) = 0;
};

其中,CreateInstance用於建立對應的COM對象。那麼,客戶端建立COM對象的過程就應該是:code

  • 客戶端調用COM庫中CoCreateInstance函數或者CoGetClassObject函數
  • COM庫從註冊表中找到相應的DLL程序並載入到進程中
  • 調用組件程序中DllGetClassObject函數,建立類廠,並把類廠接口指針返回給CoGetClassObject函數或者CoCreateInstance函數
  • 而後建立類廠對象,進而類廠建立COM對象,類廠把COM對象返回給CoGetClassObject函數或者CoCreateInstance函數,最後客戶端能夠直接調用COM對象。

COM組件支持兩種方式的重用,分別是包容(containment/delegation)和聚合(aggregation),如圖3所示。

 a) containment  b) aggregation

圖3 COM組件的兩種重用方法

Containment。對象A包含在對象B中,客戶端想要調用對象A中的方法時,須要經過對象B來調用。

Aggregation。對象A的接口暴露在對象B的外面。當客戶端想要調用對象A中的方法時,直接調用。可是客戶端並不知道對象A的存在。

 


 

 .NET中使用的是程序集(assembly)這個概念。使用C#編寫的程序編譯後成爲程序集(.dll或者.exe格式的文件)。程序集的組成如圖4所示。

 圖4 程序集的組成

其中,程序集列表是必須有的(assembly manifest)。程序集列表包括該程序集元數據,例如與指定程序集版本要求、安全標識所需的全部元數據,以及定義程序集範圍和解析對資源和類的引用所需的全部元數據。

程序集列表中的內容包括:

assembly name、version number、culture、strong name information (這四項組成了程序集的標識)、list of all files in the assembly、type reference information、information on referenced assemblies

https://docs.microsoft.com/en-us/dotnet/framework/app-domains/assembly-manifest

程序集中無需使用IDL文件來定義組件接口的信息,取而代之的是元數據(metadata)。元數據包括程序集的一切基本信息,好比版本、類型、命名空間、依賴的其餘程序集信息等。一個.dll文件中的元數據信息能夠經過reflection獲取(包括命名空間、類、屬性、方法等)。編譯器會自動地把程序中的這些相關信息封裝在程序集的元數據中。所以,能夠說程序集是一種自描述的組件。元數據的使用也使得程序集無需像COM組件,在使用前須要註冊。詳情可見:

https://docs.microsoft.com/en-us/dotnet/standard/metadata-and-self-describing-components

MSIL code是指程序集會首先被編譯成一種微軟中間語言(Microsoft Intermediate Language),程序不管是用C#寫仍是VB寫,編譯成IL都是等效的。.NET平臺是創建在CLR(Common Language Runtime)基礎上的,也就是說用C#寫的程序要經歷過兩次譯碼才能在機器上運行,這與C++是不同的。第一次譯碼是轉換成IL,第二次纔是轉換成與操做系統相匹配的二進制指令。第二次是CLR負責的。這樣運行在CLR基礎上的被稱爲託管代碼,而COM組件則是用非託管代碼實現的。

resources就是指程序集包含的一些可用資源,這些資源在程序集運行時是可使用的,包括字符串、圖片以及特殊文件等。

所以,.NET組件(assembly)與COM組件相比具備自描述、自包含的特色。其在使用時無需註冊,在建立時也無需使用COM庫和類工廠,接口定義和實現也不是分開的。

COM組件的二進制兼容性是經過使用接口指針和虛函數表實現的,而.NET組件的二進制兼容性是經過使用元數據實現的。

相關文章
相關標籤/搜索