HyperLink
Bejelentkezés
E-mail: 
Jelszó: 





Skip Navigation Links
 

COM komponensek használata .NET rendszerben


Példaprogram letöltése

36467 bájt

A COM komponensek régóta használt elemei a nyelv-független programozásnak. Windows környezetben sokszor találkozhatunk velük, így elkerülhetetlen, hogy ismerjük elérésük és felhasználásuk módját a .NET rendszerben fejlesztett kódból. Ezt szem előtt tartva cikkünkben felvázoljuk a COM komponensek, és a menedzselt kód együttműködésének elméleti alapjait.

COM komponensekről röviden
A COM komponensek olyan önálló egységek, melyek bináris formában jelennek meg, rendszerint egy DLL vagy egy EXE fájl formájában.
Egy komponens tulajdonképpen több úgynevezett COCLASS (COM osztály) összefogása. Egy COCLASS több interfészt is megvalósíthat. Ha egy COCLASS valamilyen interfészt megvalósít, akkor az azt jelenti, hogy a COCLASS valamilyen képességgel rendelkezik. Egy COCLASS nagyon hasonló az objektum-orientált szemléletmódban megszokott osztályhoz.
Az interfészekhez metódusokat definiálhatunk, melyek valamilyen működésre lesznek majd képesek. Az interfész csak egy definíció, melyhez az összes, az interfészt megvalósító osztálynak ragaszkodnia kell. Az interfész csak meghatározza, hogy minek kell történnie, azonban ennek megvalósítását az osztályra bízza.
Az interfészek, a COCLASS azonosítására egy 128 bites szám szolgál (GUID, Globally Unique IDentifyer). Egyedi azonosító, melynek generálása annyira sok összetevőn múlik, hogy szinte kizárt egy azonosító két objektumhoz rendelése.
A COM interfészeket valamilyen programozási nyelvtől független módon kell definiálni, hogy a komponensek készítésének és használatának programozási nyelve független tudjon lenni. Ennek egyik módja az IDL (Interface Definition Language). Ha az interfész IDL nyelven van megfogalmazva, akkor ezt követően egy IDL fordítóval tudjuk azt a többi programnyelv számára érthető formába konvertálni.
Egy másik módszer, hogy valamilyen szabványos, bináris formában tároljuk az interfésszel kapcsolatos információkat. Ez COM esetén a TYPE LIBRARY, vagy típuskönyvtár, melyet vagy egy különálló TLB kiterjesztésű állomány tartalmaz, vagy maga a komponens.
A COM komponensek alapvető interfésze az IUnknown, ezt minden komponensnek biztosítania kell. Az IUnknown interfész lehetővé teszi, hogy a COM-kliens mutatókat kapjon a komponens egyéb használható interfészeire. Annak érdekében, hogy lekérdezzük, milyen interfészek állnak rendelkezésre, a QueryInterface metódus szolgál. Tulajdonképpen a komponensek valamennyi interfésze ebből az alap interfészből származik közvetlenül, vagy közvetve.
Az interfész másik két metódusa az AddRef és a Release. A kliensnek minden interfészpointerre legelőször az AddRef metódust kell meghívnia, majd amikor nem használ egy adott interfészpointert, meg kell hívnia a Release metódust. Az AddRef metódussal emeljük az interfészre mutató hivatkozások számát, a Release metódussal csökkentjük.
Ez lehetővé teszi, hogy a COM komponens saját maga tartsa nyilván, hogy hányan használják, vagyis, hogy hány használatban lévő interfészpointer van még, ami a komponens valamely interfészére mutat. Ha már egy sincs, a komponens kitöltődhet a memóriából.
A COM komponensek nyelv-független megvalósítására jellemző, hogy akár script-nyelvekből is elérhetők. A JScript nyelvben – mivel minden változó egy–egy objektum - így elegendő a CreateObject metódust meghívni a komponens példányának létrehozásához, paraméterként átadva a komponens azonosítóját (ProgId).
COM objektumok elérése .NET-ben
Amikor COM komponenseket és .NET objektumokat használunk egy alkalmazáson belül, a legfontosabb különbség a két objektum-típus között a memóriahasználatban van. A .NET objektumok a menedzselt memóriában találhatóak, melyet a Common Language Runtime (CLR) tart felügyelete alatt. Szükség esetén el is távolítja az objektumokat a memóriából.
A COM objektumok számára az úgynevezett nem-menedzselt memóriában foglalódik le terület, és várhatóan nem kerülnek át másik memóriaterületre életük során.
A Visual Studio és a .NET Framework karöltve biztosítanak eszközöket ahhoz, hogy a kétfajta memóriaterület között a szükséges kapcsolat megvalósuljon, vagyis a kétfajta objektumtípus képviselői kommunikálhassanak egymással.
Manapság az alkalmazások többsége használ COM komponenseket. Bár a .NET által megvalósított assembly-k elve némileg túlhalad a COM elméleteken, vannak esetek, amikor elkerülhetetlen használatuk. Ilyen eset például a Microsoft Office csomaggal telepített komponensek halmaza, melyek segítségével a legváltozatosabb funkciók is könnyedén elvégezhetőek. Amíg a COM komponensek alapvetően a Windows-os környezethez kötődnek, addig az assembly-kkel megvalósított szoftverfejlesztés a CLR kapcsán az önálló .NET Platformhoz, kihasználva annak számtalan előnyét.
A .NET Platformon történő fejlesztés megadja ugyanakkor annak lehetőségét, hogy már meglévő COM komponensek funkcionalitását beépítsük alkalmazásainkba. Ezt az úgynevezett COM interoperabilitás nevű technológia teszi lehetővé. A COM objektumok eléréséhez „Interop assembly”-ket használhatunk, melyek segítenek kapcsolatot építeni a menedzselt kód és a COM között.
A COM objektumok karakterisztikáját a típuskönyvtárak írják le, míg a .NET rendszerben az assembly manifeszt alkalmas arra, hogy egy menedzselt egység jellemzőit tartalmazza. A .NET típus importáló és exportáló eszközeinek segítségével (tlbimp.exe és tlbexp.exe) könnyedén generálhatunk típuskönyvtárakat assembly-kből, és importálhatjuk be a típuskönyvtárakban tárolt információt assembly-kbe. Ebből talán már látható, milyen könnyen hozhatóak „közös nevezőre” a két rendszer alkotói.
Az Interop assembly-k képeznek hidat a COM objektumok és a .NET assembly-k között, menedzselt tagokat rendelve a nem-menedzselt kód tagjaihoz (változók, struktúrák, stb.). Az összes, COM-al kapcsolatos művelet elvégzése az ő feladatuk. Ilyen művelet a MARSHALING. A műveletre azért van szükség, mert a COM komponensek metódusaiban a paraméterek, visszatérési értékek típusai nem minden esetben fedhetők le menedzselt kódbeli típusokkal, így a kezelő mintegy becsomagolja a COM típust, majd így adja vissza azt a hívó kódnak.
Interop Marshaling és COM marshaling
A legtöbb típusnak van egy reprezentációja mind a menedzselt, mind a nem-menedzselt memóriaterületen. Más típusok nem is rendelkeznek reprezentációval a menedzselt memóriaterületen, vagy kétértelmű típussal rendelkeznek. A kezelő (marshaler) segít ezen típusok összerendezésében.
A kétértelmű típusok esetén vagy hiányzik a típusinformáció (például egy tömb mérete), vagy több reprezentáció van jelen a nem-menedzselt memóriaterületen, és rendelődik egy önálló típushoz. Az ilyen típusokhoz a kezelőnek explicit utasításokat kell adjunk arra vonatkozóan, hogy milyen módon kezelje az adott típust, és az összerendelést.
A procedúra minden esetben lezajlik, amikor a hívó és a hívott objektum nem tud ugyanazon az adatpéldányon dolgozni. A módszer egyedisége, hogy a kétfajta objektum akkor is ugyanazon az adatpéldányon dolgozik, ha mindkettő rendelkezik egy-egy másolattal az ominózus adatból.
Az objektumok úgynevezett APARTMENT-ben – mint logikai egységben – működnek, mely lehet közös, de működhetnek két külön egységben is. Attól függően, hogy a menedzselt objektum, és a COM komponens azonos vagy különböző apartment-ben található, beszélhetünk Interop, vagy COM marshaling eljárásról.
Abban az esetben, ha az apartment közös, akkor az Interop marshaling automatikusan elvégez minden típus-összerendelést.


Amennyiben a két objektum külön apartment-ben található, akkor úgynevezett apartment-közi (cross-apartment) hívásra van szükség, vagyis mindkét típus-összerendezési eljárás megvalósul.
Amikor .NET-ben egy COM komponenst használni szeretnénk, akkor nem teszünk mást, mint a típuskönyvtárban definiált információkat egy assembly-be importáljuk a .NET tlbimp.exe eszközével, vagy egyszerűen referenciaként megadjuk a projektünkben, helyi másolatot (kész assembly-t) kapva eredményül. A COM típusok definíciói az assembly-be kerülnek, és a hívó alkalmazásban csak példányosítjuk a COM komponenst reprezentáló osztályt, vagy implementáljuk interfészét. Ekkor a komponensre való hivatkozások számát a CLR tartja nyilván (hívja meg az első szakaszban említett AddRef és Release metódusait az adott komponensnek), a nem-hivatkozott komponensek pedig a szemétgyűjtés (garbage collection) eredményeképpen eltűnnek a memóriából, akár csak egy menedzselt objektum.
Burkoló osztályok
A COM objektumokkal történő munka során kétféle hívásról beszélhetünk. A COM kliensek hívhatnak .NET objektumokat, vagy a .NET kliensek hívnak meg COM szervereket. A két híváskor kétféle, de mindenképpen szükséges burkoló objektumok jönnek létre. Ennek az oka, hogy a COM komponensek, és a .NET objektumok alapvetően különböző természetűek. Ezek vázlatosan a következők:
  • COM komponensek esetén a hívó kliensek menedzselik a hívott objektum élettartalmát, míg a .NET rendszerben ez a feladat a CLR-re hárul.
  • A COM kliensek úgy ellenőrzik a komponens használhatóságát, hogy küldenek egy kérést a használni kívánt interfésznek, és ellenőrzik, hogy kaptak-e vissza interfészmutatót, vagy sem. .NET esetében a kliensek a „Reflection” technológiát használják az objektumok elérhetőségének vizsgálatára.
  • A COM komponensek kliensei csak egy pointert kapnak a komponensre (interfészeikre), így csak bízni tudnak abban, hogy az objektum azonos helyen marad a memóriában. Ellenőrzésre nincs lehetőségük. .NET rendszerben a hívott objektumok tetszőleges helyen lehetnek a memóriában, a futtatórendszer tökéletesen felügyeli azok mozgását.
Ezeknek a különbségeknek az áthidalására jönnek létre a burkoló osztályok, így mindkét objektumfajta előtt úgy tetszik, hogy egy azonos környezetben található objektumot hív meg. Amikor a menedzselt kód hív egy nem-menedzselt COM komponenst, akkor az úgynevezett Runtime Callable Wrapper (RCW) jön létre a futtatórendszer jóvoltából. Ellentétes irányú híváskor egy COM Callable Wrapper (CCW) jön létre, elsimítva a különbségeket.
Létező COM komponens elérése
A mellékelt WinCOMClient projektben egy létező COM objektumot érünk el, melynek segítségével képesek vagyunk avi állományokat lejátszani. Ekkor a gyorsmenüben az Add reference menüponttal hozzáadhatjuk a COM komponens típuskönyvtárából létrehozott assembly-t a projektünkhöz, majd meghívhatjuk az assembly-ben definiált osztály metódusát.
A felhasználandó COM komponenst a megjelenő ablak COM füle alatt választhatjuk ki, neve ActiveMovie control type library 1.0, mely a Windows rendszermappájában található QUARTZ.DLL néven.
A komponens neve QuartzTypeLib, melyet használnunk kell a forráskódban.
A komponens osztályát példányosítjuk első lépésben.
QuartzTypeLib.FilgraphManager graphManager = new QuartzTypeLib.FilgraphManager();
Majd előállítunk egy IMediaControl interfészt, melynek a RenderFile és a Run metódusai segítségével játsszuk le a mellékelt clock.avi állományt.
QuartzTypeLib.IMediaControl control = (QuartzTypeLib.IMediaControl)graphManager;
control.RenderFile("clock.avi");
control.Run();
COM objektum készítése, és elérése
A mellékelt COMClient és COMServer projektek tartalmazzák a megvalósított COM szerver és kliens-alkalmazásokat. A COMServer projekt tulajdonságai között be kell állítani, hogy a létrejövő assembly COM komponensként is üzemeljen. Ezzel a művelettel a REGASM.EXE alkalmazás funkciói válthatóak ki.
A szerver tartalmaz egy interfészt, melynek regisztrálásához megadunk egy GUID azonosítót.
[Guid("A1EB5A26-25CF-48c7-81D9-BE95BAF9D677")]
public interface ICOMInterface
{
  string COMWrite(string name);
}
Az interfész egyetlen, szöveget visszaadó metódusát megvalósítjuk a Server osztályban, mely szintén tartalmaz egy azonosítót.
[Guid("EA4A2EFD-CC95-4d7a-AF70-4189B3ED7BA2")]
public class Server : ICOMInterface
{
  public string COMWrite(string name)
  {
    return "Üdvözlöm, kedves " + name;
  }    
}
Az IDE Tools menüjéből elérhető OLE/COM Object Viewer alkalmazása segítségével meg is nézhetjük, hogy fordítás után megjelenik az objektum, mint regisztrált COM komponens. A .NET Categories alkönyvtárban kell keresnünk a COMServer.Server bejegyzést.
A COMClient alkalmazásban el is érhetjük a COM komponenst, anélkül, hogy a referenciát megadtuk volna a típusra. Ehhez egy példányt kell létrehoznunk a COMServer.Server ProgId felhasználásával.
Type t = Type.GetTypeFromProgID("COMServer.Server");
Majd aktiválnunk kell azt.
object obj = Activator.CreateInstance(t);
Egy objektum-tömbben megadjuk a COMWrite meghívandó metódus paraméterét, mely most a textBox1 szövegmezőben megadott név lesz.
object[] arguments = {textBox1.Text};
Majd a típus InvokeMember metódusával meghívjuk a példány tagfüggvényét.
object s = t.InvokeMember("COMWrite",BindingFlags.InvokeMethod,null,obj,arguments);
Az első paraméter tartalmazza a hívandó metódus nevét, a második paraméterben adjuk meg, hogy egy metódusról van szó.
A visszaadott értéket pedig karakterlánccá konvertálva visszaadjuk.
textBox2.Text = s.ToString();

Cikksorozat

#IDKategóriaCikk címeSorozat
2591WindowsTippek és trükkök - RAS - Modem csengetési szám állítása1. rész
2622WindowsTippek és trükkök - Program futtatása más felhasználóként2. rész
2640WindowsA Windows ikonméretének megváltoztatása és Windows 2000 Asztaltémák3. rész
2657WindowsTippek és trükkök - Internet Explorer4. rész
2667WindowsTippek és trükkök5. rész
2684WindowsAlapértelmezések állítása, telepítési fájlok helye, intéző nézetek6. rész
2696WindowsBiztonsági trükkök7. rész
2702WindowsWindows XP trükkök8. rész
2729WindowsWindows 2000 és XP tippek, trükkök9. rész
2757WindowsRegistry trükkök10. rész
2784WindowsTippek, trükkök11. rész
2829WindowsTippek, trükkök12. rész
2889WindowsWindows XP tippek13. rész
2909WindowsTippek Windows XP-hez14. rész
2919WindowsWindows tippek15. rész
2924WindowsWindows tippek16. rész
2963WindowsWindows tippek17. rész
2973WindowsWindows Tippek18. rész
2981WindowsWindows tippek19. rész
2990WindowsTippek-trükkök20. rész
3027WindowsIIS tippek21. rész
3034WindowsWindows XP tippek-trükkök22. rész
3088WindowsWindows 2000/XP tippek, trükkök23. rész
3133WindowsWindows XP tippcsokor24. rész
3140WindowsWindows XP tippek, trükkök25. rész
3152WindowsXP és IIS tippek - trükkök26. rész
3158WindowsWindows XP tippek, trükkök27. rész
3168WindowsTippek, trükkök28. rész
3170WindowsRegistry trükkök29. rész
3179WindowsTippek, trükkök30. rész
3197WindowsWindows XP tippek, trükkök31. rész
3205WindowsTippek, trükkök32. rész
3214WindowsTippek, trükkök33. rész
3223WindowsTippek, trükkök34. rész
3233WindowsTippek, trükkök35. rész
3271WindowsTippek, trükkök36. rész
3307WindowsTippek, trükkök37. rész
3370WindowsTippek, trükkök38. rész
3399WindowsTippek, trükkök39. rész
3510WindowsTippek, trükkök40. rész
3611WindowsHardverrel kapcsolatos tippek, trükkök41. rész
3668WindowsRegistry trükkök42. rész
3711WindowsTippek, trükkök43. rész
3771WindowsTippek, trükkök44. rész
3801WindowsTippek, trükkök45. rész
3831WindowsTippek, trükkök46. rész
3891WindowsTippek, trükkök47. rész
3921WindowsTippek, trükkök48. rész
3981WindowsTippek, trükkök49. rész
4041WindowsTippek, trükkök50. rész
4071WindowsTippek, trükkök51. rész
4151WindowsTippek, trükkök52. rész
4171C#Tippek, trükkök53. rész
4211WindowsTippek, trükkök54. rész
4251WindowsTippek, trükkök55. rész
4281WindowsTippek, trükkök56. rész
3589DelphiTippek, trükkök57. rész
3718DelphiTippek, trükkök58. rész


Könyv
Ez a cikk megtalálható ebben a könyvben: C# Software Offline 2003 évkönyv 418. oldal

Felhasználási feltételek
A Software Online szoftverfejlesztői magazin mindegyik cikke, minden megjelent képe, és egyéb publikált anyaga szerzői jog védelme alatt áll! Bármilyen formában történő másodlagos terjesztésük, közzétételük vagy felhasználásuk kizárólag a kiadó előzetes írásbeli engedélyével történhet!

Copyright © 1999-2012 Animare Software Kft. Minden jog fenntartva!
| Készült: Animare Stúdió | Adatvédelem | Kapcsolat |