C#开发COM组件
原文:http://blog.csdn.net/soudog/article/details/1593346
1.????概述
???????Microsoft在解決和以往的COM和SDK開發技術之間的互操作性(Interoperability)方面做了很多的工作,其中包括COM和.NET對象之間的相互調用以及.NET如何調用SDK中的Windows庫函數。本文試圖用一種實踐的方式探索COM和.NET對象之間的互操作(Interoperability)的實現以及相關的技術。
2.????發展歷史
???????在面向對象技術發展的初期開始暴露出來了很多的問題,其中一個就是隨著系統的復雜度不斷上升,系統的類開始出現爆炸,而且對象之間的調用依賴無法在一個更高的抽象層次上彼此之間的松散耦合,這也因此導致了這種基于源代碼的復用方式變得非常脆弱。基于組件的開發技術很好地解決了上面的問題,它在組件(某個功能的聚合,是一個類的集合)這個層次上實現了抽象和復用。在這個時期,COM(Component Object Model)技術作為這么一種方法論的實現方式開始展現它獨特的魅力,而Microsoft則帶領著IT界把這一技術推向了穩定、成熟。
???????而到了20世紀90年代末期,隨著商業邏輯處理的復雜化以及很多個性化的需求的出現,軟件復雜度也開始提高,COM技術在應用技術領域也開始顯得力不從心了。在這個時候就需要一種更靈活的、基于標準的技術來支撐應用軟件的開發,.NET作為一個具有跨時代意義的應用軟件的開發平臺悄然而至。.NET以一種基于平臺方式(應用軟件依賴于某個平臺,可移植性依賴于平臺),又在一個更高的層次上實現了軟件的復用。
3.????問題描述
???????為了保持.NET和COM技術的可互操作性,Microsoft提供一個專門的組件來解決這個問題,可以參考命名空間System.Runtime.InteropService。它不為.NET對原有的COM組件的調用提供了一種有效的方式,同時也為用.NET編寫COM組件提供一種便利。
4.????步驟
Step1.?構建.NET組件,并設置它的COM組件可見性
Step2.?定義COM組件接口
Step3.?實現COM組件接口
Step4.?部署
Step5.?測試
Step 1構建.NET組件
n?????????新建一個.NET組件,如下圖:
n?????????設置這個.NET組件的COM可見性
設置工程屬性:“生成”->?“為COM Interop注冊”。
當然也可以為每個接口設置COM可見性,ComVisibleAttribute類提供了這樣的控制。
Step 2定義組件接口
???????每個COM組件接口都有一個唯一的GUID,在.NET接口的定義中由Guid屬性來指定
???????在這個例子中我定義了如下的接口:
?
[TypeLibType(4160)] [Guid("F0485D81-59C1-44b1-9316-D474E26C026E")] public?interface?IXMPReader { [DispId(0)] string?Metadata?{?get;set;} [DispId(1)] IXMPTemplate?ReadTemplate(string?xPath); }Step 3實現組件接口
每個COM組件接口的實現類也都有一個唯一的GUID,由Guid屬性來定定義,
在IDL中對組件類的定義需要有一個Default(默認實現的接口聲明),?在.NET組件中由ComDefaultInterface屬性來定義。
在這個例子中我是這樣實現了這個接口的,如下:
???
namespace?XMPTemplate { [TypeLibType(4160)] [Guid("AD665240-9E4D-4c30-9475-023EA44E41BD")] [ComDefaultInterface(typeof(IXMPReader))] [ComSourceInterfaces(typeof(IXMPReader))] public?class?XMPReader?:?IXMPReader { private?string?_metadata=""; public?string?Metadata { get?{?return?_metadata; } set?{?_metadata?=?value; ; } } public?IXMPTemplate?ReadTemplate(string?xPath) { XmlDocument?document?=?new?XmlDocument(); document.LoadXml(Metadata); XmlNode?node?=?document.SelectSingleNode(xPath); XMPTemplate?template?=?new?XMPTemplate(); template.LoadXml(node.InnerXml); return?template; } }?
?
?
?
??
?
?
?
?
Step 4部署
???????假設我們生成的.NET組件的名稱是XMPTemplate.dll,訪問路徑為C:/ XMPTemplate.dll
n?????????利用Regasm工具來注冊.NET組件
regasm C:/ XMPTemplate.dll
n?????????將這個.NET組件加入到全局程序集緩存中
Gacutil /I C:/ XMPTemplate.dll
Step 5?測試
n?????????VC++調用
| const?wchar_t*?progid?=?L"XMPTemplate.XMPReader"; CLSID?clsid?=?CLSID_NULL; HRESULT?hr?=?CLSIDFromProgID(progid,&clsid); IDispatch*?pDispatch?=?NULL; CoCreateInstance(clsid,NULL,CLSCTX_INPROC,IID_IDispatch,(void**)&pDispatch); ATL::CComVariant?varMetadata?=?tenant->GetMedata().c_str(); ATL::CComVariant?varResult; DISPPARAMS?params?= {&varMetadata,?NULL, 1, 0 }; pDispatch->Invoke(0,?IID_NULL,?LOCALE_USER_DEFAULT,?DISPATCH_PROPERTYPUT, ¶ms, &varResult,?NULL,?NULL); ? varResult.Clear(); ATL::CComVariant?varXPath?=?L"//"; DISPPARAMS?paramsXPath?={&varXPath,?NULL, 1, 0 }; pDispatch->Invoke(1,?IID_NULL,?LOCALE_USER_DEFAULT,?DISPATCH_PROPERTYGET, ¶msXPath, &varResult,?NULL,?NULL); pDispatch->Release(); |
總結
- 上一篇: win8.1安装veket的方法
- 下一篇: COM 组件设计与应用(十一)—— ID