走近COM Interop——RCW基礎(chǔ)
發(fā)表時(shí)間:2023-04-07 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]走近COM Interop—— RCW入門(mén) 緒言 由于目前加入了一個(gè)負(fù)責(zé)將原有系統(tǒng)移植至.Net平臺(tái)的項(xiàng)目組,花了些時(shí)間對(duì)COM-->.Net進(jìn)行了些基礎(chǔ)研究。貼出此文,希望與各位...
走近COM Interop
—— RCW入門(mén)
緒言
由于目前加入了一個(gè)負(fù)責(zé)將原有系統(tǒng)移植至.Net平臺(tái)的項(xiàng)目組,花了些時(shí)間對(duì)COM-->.Net進(jìn)行了些基礎(chǔ)研究。貼出此文,希望與各位分享。不足之處,請(qǐng)各位指正。先謝啦。
一、基礎(chǔ)概念
什么是COM Interop?COM Interop看上去象是介乎于COM和.Net之間的一條紐帶,一座橋梁。為了保持向后兼容,COM Interop可以使得.Net程序在不修改原有COM組件的前提下方便的訪問(wèn)COM組件。這一點(diǎn)是非常重要的。事實(shí)上,全球的COM組件的代碼量估計(jì)可能有數(shù)十億行,擁有這些COM組件的公司不可能重寫(xiě)這些組件,所以COM Interop的存在為有此需求的開(kāi)發(fā)者提供了很好的解決方案。
大家都知道,COM和.NET之間存在著非常大的差異,為了使兩者可以有機(jī)的結(jié)合在一起進(jìn)行協(xié)同工作,COM Interop中實(shí)際存在著2種橋接方式。一種是RCW,Runtime Callable Wrapper(水平有限,不知道精確的翻譯是什么,這兒就不予詳解了。);另一種是CCW,COM Callable Wrapper。后者,將在后續(xù)的相關(guān)文章中進(jìn)行討論,這兒就不再贅述了,本文主要關(guān)注的是前者。RCW是在運(yùn)行時(shí)通過(guò)CLR從Interop裝配件(Interop Assembly)的元數(shù)據(jù)中獲取相關(guān)信息動(dòng)態(tài)的實(shí)例化而得到的。個(gè)人認(rèn)為,可以把它理解為是介乎于COM和.Net應(yīng)用程序之間的一個(gè)代理,.Net應(yīng)用程序?qū)OM組件的每個(gè)調(diào)用請(qǐng)求都是通過(guò)這個(gè)RCW中轉(zhuǎn)的。使用者將感覺(jué)不到自己是在調(diào)用COM組件,一切都是這么的自然,和調(diào)用一個(gè).Net組件沒(méi)有任何區(qū)別。使用C++的朋友都知道,在C++中如果想要實(shí)例化一個(gè)COM對(duì)象,需要使用CoCreateInstance。而當(dāng)我們有了RCW之后,一切都變得簡(jiǎn)單,我們可以在C#中使用new來(lái)直接實(shí)例化這個(gè)COM對(duì)象。
需要注意的是,一個(gè)COM組件(指的是一個(gè)實(shí)例,即一個(gè)DLL文件)由且僅由一個(gè)RCW負(fù)責(zé)維護(hù)。那么這兒有一個(gè)問(wèn)題了,對(duì)于一個(gè)COM組件的不同版本,是不是就會(huì)有不同的RCW與之相對(duì)應(yīng)呢?答案是肯定的。那有些朋友會(huì)說(shuō),.Net中的組件不是已經(jīng)解決了COM中的“DLL HELL”問(wèn)題了嗎?按上面的說(shuō)法,似乎并沒(méi)有得到解決嘛?這兒我要說(shuō)的是,在.Net中導(dǎo)入一個(gè)COM組件的不同版本,是會(huì)出現(xiàn)此類(lèi)問(wèn)題。解決此類(lèi)問(wèn)題的方法是使用PIA(Primary Interop Assembly),這部分不在本文的討論范圍之內(nèi),我將在后續(xù)的相關(guān)文章中和大家進(jìn)行討論。
二、實(shí)戰(zhàn)演練
.Net提供三種途徑供我們導(dǎo)入一個(gè)COM組件:
- 通過(guò)Visual Studio .Net提從的“添加引用”功能
- 通過(guò)命令行方式——TLBIMP.EXE
- 使用System.Runtime.InteropServices.TypeLibConverter類(lèi)編程實(shí)現(xiàn)導(dǎo)入功能
第一種方式無(wú)須贅述,非常的簡(jiǎn)單。第三種方式我會(huì)說(shuō)明PIA的用法的同時(shí),對(duì)此方法的使用加以說(shuō)明。不過(guò),我的水平不高,各位不要要求太高嘍。^_^ 言歸正傳,本文關(guān)注的是第二種方式。我們可以直接使用此工具提供的最簡(jiǎn)單的調(diào)用方式:TLBIMP TestObj.dll。但需要提醒各位的是,如果我們使用這種方式導(dǎo)入一個(gè)COM組件的話(huà),我們將“犧牲”原有的COM組件,這樣做是很危險(xiǎn)的。個(gè)人認(rèn)為,最簡(jiǎn)單的調(diào)用方式是TLBIMP TestObj.dll /out:interop.TestObjLib.dll。這樣,執(zhí)行后將會(huì)產(chǎn)生一個(gè)名為interop.TestObjLib.dll的COM Interop。下面將給出簡(jiǎn)單的例子以說(shuō)明整個(gè)過(guò)程。
1、首先用VB寫(xiě)的一個(gè)簡(jiǎn)單的ActiveX Dll
'Project name is TestObjList, class name is TestObj
Option Explicit
Public Function Add(ByVal iValue As Integer) As Integer
Add = iValue + 1
End Function
2、使用命令行工具導(dǎo)入這個(gè)COM組件
TLBIMP TestObjLib.dll /out:interop.TestObjLib.dll
3、在一個(gè).Net Windows Forms中寫(xiě)一段調(diào)用此組件的測(cè)試代碼
using interop.TestObjLib;
private void button1_Click(object sender, System.EventArgs e)
{
TestObjClass obj = new TestObjClass();
int num = 1;
MessageBox.Show(obj.Add(num).ToString());
}
此處需要說(shuō)明一點(diǎn),當(dāng)TLBIMP.EXE在生成Interop裝配件時(shí)會(huì)在原COM中的類(lèi)的名字后面加上一個(gè)"Class"。調(diào)用時(shí),請(qǐng)各位注意。