Die Community zu .NET und Classic VB.
Menü

COM als Middleware - Seite 10

 von 

2.5 Proxies und Stub als Stellvertreter
Nächste Seite >>
2.3 Eventfähigkeit, IConnectionPoint & IConnectionPointContainer
<< Vorherige Seite

2.4 Persistenz  

Die Lebensdauer eines Objekts beschränkt sich auf die Laufzeit seines Clients. Die Eigenschaft der Persistenz [engl.: to persist: bestehen, fortdauern] hingegen befähigt ein Objekt, seinen üblicherweise temporären Zustand, in einem dauerhaften Speicher abzulegen, respektive sich aus ihm heraus wieder zu restaurieren. COM bietet zur Umsetzung der Objektpersistenz die Standardschnittstellen IPersistFile, IPersistStream, sowie IPersistStorage an.

IPersistFile ermöglicht den aktuellen Zustand eines Objekts in und aus einer Datei linear zu konvertieren. Ein Client erfährt mittels der Methode IsDirty über einen vorangegangenen Zustandswechsel eines Objektes seit dessen letzter Speicherung und stößt im weiteren über die Methode Save die Zustandssicherung an. Bei erneuter Initialisierung der persistenten Instanz ruft COM die dritte Methode IPersistFile::Load auf. Die Auswahl der persistenten Daten trifft der Entwickler über die gezielte Implementierung der jeweiligen Schnittstellenfunktionen. Die mit den Persistenzinformationen versehene Datei ist entweder als eigene Extension auf den betroffenen Server anzumelden oder durch eine binäre Chiffrierung zu authentifizieren. Letztere erfolgt anhand der Schnittstellen-IID durch einen Eintrag in der Registry unter dem Schlüssel HKEY_CLASSES_ROOT\FileType. Jedem Interface lassen sich mehrere parametrierbare Chiffrierungen zuordnen. Die Codierung ist durch ein Bitmuster, einer Maske sowie dem Dateioffset bestimmt.

Verbunddokumente [Compound Documents] bestehen aus mindestens einem bis zu einer Vielzahl von Objekten. Um zu vermeiden, dass ein solches Dokument eine große und damit unübersichtliche Menge von Persistenzdateien generiert, bietet COM mit Structured Storage eine Technik an, die die Zusammenfassung mehrerer Persistenzen in einer Datei gewährt. Anhand der Standardschnittstellen IStorage und IStream lässt sich übereinstimmend mit einem Verzeichnismodell eine hierarchische Struktur erstellen. Verzweigend von einem Wurzelobjekt bilden sich rekursiv IStream-Objekte und IStorage-Objekte aus. IStorage-Objekte entsprechen hierbei den Knoten [vergleichsweise Ordner], IStream-Objekte einer zugeordneten spezifischen Information [vergleichsweise Datei]. Die Erzeugung, bzw. der Zugriff dieser Persistenzstruktur erfolgt dynamisch zur Laufzeit über die API-Funktionen StgCreateDocfile bzw. StgOpenStorage. Die stringbehaftete Navigation durch die Verzeichnisstruktur verläuft über den zurückgegebenen Schnittstellenzeiger auf das IStorage-Objekt und via Monikers [s. Kapitel 2.4.1]. Jeder Storageknoten ist über seine vermerkte IID eindeutig einer Schnittstelle zugewiesen und damit an eine spezifische COM-Klasse gekoppelt. Ein Storageknoten beinhaltet optional weitere Storageknoten und mindestens ein bis mehrere Streams, auf die über die IStream-Methoden Read und Write Zugriff besteht.

2.4.1 Monikers, Namensgebung und Bindung

Die englische Bezeichnung Moniker bedeutet übersetzt soviel wie "Spitzname". Im COM-Sinne sind Monikers benannte Verweise auf Objekte und dienen einem Client zur assoziativen Referenzierung, auch assoziatives Binden genannt. Ein Moniker stellt den Repräsentanten eines Objekts dar. Er ist bestimmt durch die Vergabe eines einprägsamen Namens in Form einer Zeichenkette. Der Moniker selbst ist eine meist in Dlls einkompilierte Komponente und durch die von IPersistStream abgeleitete Schnittstelle IMoniker eindeutig beschrieben. COM verwendet Monikers um Objekte ortstransparent zu aktivieren und zu verbinden. Typische Anwendungsbeispiele sind die mit Word oder Excel erstellbaren Compound Documents. Ein Word-Dokument umfasst eine Menge von benannten Objektverweisen, also Monikers und erfüllt damit die Bedingung einer Linkliste oder genauer, die eines Containers. Diese Quellen, auch als Item oder Link bezeichnet, können vielseitiger Natur sein. Veranschaulichend sei hier die Zwischenablage, der Objekt einfügen Dialog oder Drag & Drop genannt. Es ergeben sich zwei Betrachtungsweisen für einen Moniker:

Client Ein Moniker-Client ist eine Anwendung die einen Moniker verwendet, um eine Komponente namentlich zu referenzieren. Programmtechnisch initiiert der Client durch den Interfacezeiger auf eine IMoniker implementierenden Komponente den Vorgang des namentlichen Bindens. Der Ablauf bleibt hierbei für den Client transparent.
Provider Ein Moniker-Provider ist eine IMoniker implementierende Komponente. Sie gestattet dadurch einem Client den Zugriff auf Objekte des zugehörigen Servers über einen Moniker. Ein Server sollte über IMoniker verfügen, wenn mindestens eines seiner Objekte Persistenz fordert und er die Kontrolle über den damit verbundenen Speichervorgang benötigt. Provider müssen zur Instanzierung der Serverobjekte IClassFactory nicht implementieren.

Ein Moniker kann eine Vielzahl unterschiedlicher Objekte binden. Um ein Objekt über einen Moniker zu referenzieren, ruft der Client lediglich die Methode IMoniker::BindToObject auf, unabhängig davon ob das Objekt ein vollständiges Word-Dokument oder eine einzelne Excelzelle beschreibt. Ist das benannte Objekt bereits anderweitig instanziert, lokalisiert BindToObject es im Speicher; liegt es hingegen passiv als Datei vor, startet die Methode den zugehörigen Server, um daraufhin das angeforderte Objekt von ihm zu erhalten.


Abbildung 12: Namentliche Referenzierung eines Objekt über einen Moniker

Zwecks eindeutiger Objekt-Identifikation muss ein Provider den passenden Moniker aus einer geeigneten Monikerklasse erstellen können. Eine solche Klasse verweist auf eine typenspezifische Implementierung der IMoniker-Schnittstelle. Neben der Bereitstellung diverser Systemmoniker ermöglicht COM auch die Verwendung benutzerdefinierter Monikertypen. Die Notwendigkeit benutzerdefinierter Umsetzungen der IMoniker-Schnittstelle ist eher selten, da COM bereits eine Reihe gängiger Implementierungen offeriert:

File-Monikers beschreiben den einfachsten Monikertypen und werden dazu verwendet, persistente Objekte aus einer Datei heraus zu assoziieren. Sie kapseln einen absoluten oder relativen Dateipfad und delegieren die beim Binden notwendigen Schritte, die das Finden des verknüpften Objekts, dessen Instanzierung sowie Initialisierung an IPersistFile::Load beinhaltet, weiter. Daher muss eine Komponente die File-Moniker unterstützt, grundsätzlich auch IPersistFile implementieren. COM bietet Providern die Erstellung eines File-Monikerobjekts durch die API-Funktion CreateFileMoniker an.

Composite-Moniker verknüpfen mehrere Moniker gleichen oder verschiedenen Typs zu einer Gesamtassoziation. Der Bindevorgang dieses Moniker beschränkt sich im wesentlichen darauf, das Binden seiner umfassten Elemente zu initiieren. Die Verwendung komponierter einfacher Systemmoniker verringert die Notwendigkeit benutzerdefinierter Moniker. Die Kombination verschiedener Monikertypen erweitert den Kontext einer Komponente auf mehr als einen Namensraum. Beispielsweise definiert ein Dateisystem einen öffentlichen Namensraum, ein Container hingegen beschreibt für die in ihm gesammelten Objekte einen privaten. Composite-Moniker verbinden beide Bereiche zu einem Gesamten. Es gilt zwischen der generischen und der nicht generischen Komposition zu unterscheiden. Die generische vereinigt Moniker aus bekannten Basistypen zu einer neuen Komposition [Generic Composite Monikers]. Ihre Erstellung wird durch die API-Funktion CreateGenericComposite unterstützt. Nicht generische Moniker hingegen sind Bezeichner aus gleichen Basistypen oder aus einer neuen benutzerdefinierten Implementierung von IMoniker. Für diese Art der Kombination bietet IMoniker neben anderen, die Methode ComposeWith an. Die gebräuchlichsten Monikertypen sind File Monikers, Item Monikers und Generic Composite-Monikers.

Item-Monikers referenzieren als Teil eines Composite-Monikers ein in einem Objekt eingebettetes, weiteres Objekt. Der Container kann beispielsweise das in ein Compound Document eingefügte Spreadsheets mit einer Zelle als Unterobjekt sein. Der Item-Moniker steht in direkter Beziehung zu dem Moniker, der innerhalb des Composite Moniker vor ihm steht und wird durch das übergeordnete Objekt aufgelöst. Mehrere Item-Monikers lassen sich über einen Composite-Moniker zu einer hierarchischen Struktur verknüpfen. Es gilt zwischen echten und Pseudoobjekten zu unterscheiden. Pseudoobjekte entstehen dynamisch zur Laufzeit, beispielsweise durch eine Textselektion in einem Word-Dokument, echte hingegen liegen binär auf einem Speichermedium vor. Signifikanter Unterschied zwischen Item- und File-Moniker ist ihr Namensraum. File-Moniker besitzen im Kontext des öffentlichen Dateisystems eine globale Gültigkeit, Item-Moniker hingegen erschließen sich nur dem jeweiligen spezifischen Container. Eine Komponente, die beide Monikertypen offen legt, muss daher neben IPersistFile auch die Schnittstelle IOleItemContainer anbieten. Die API-Funktion CreateItemMoniker unterstützt die Erstellung von Item-Monikern. Unabhängig von der Kompatibilität respektive der Tiefe einer über eine Komposition gebundenen Item-Monikerstruktur bleibt der Aktivierungsvorgang für den Client auch hier transparent.

Anti-Moniker bilden das letzte Element eines Generic Composite Monikers und dienen dem Ausblenden des äußersten Monikers innerhalb der Komposition. Anti-Moniker lassen sich nicht binden, ihr Anzeigenamen ist irrelevant. Ihre Berechtigung erfahren sie lediglich durch die Implementierung der Methode IMoniker::Inverse. Diese bietet die einzige Möglichkeit Partiale in einer Komposition zu löschen. Ein Anti-Moniker kann durch API-Funktion CreateAntiMoniker erstellt werden.

Pointer-Moniker referenzieren ein Objekt, das bereits in einem aktivierten oder laufenden Zustand arbeitet durch einen Pointer. Anwendung findet dieser Typ meist in Objekten ohne Persistenz, auf die ein monikerfähiger Client nicht direkt verweisen kann oder möchte. Die ROT [s. Kapitel 2.4.2] wird hierbei übergangen, statt dessen ruft die Implementierung der Moniker-Methode BindToObject direkt IUnknown::QueryInterface auf. Da das betroffene Objekt persistenzlos ist, führt eine Operation auf die Methode IMoniker::Save zu einem Fehler. Die API-Funktion CreatePointerMoniker unterstützt die Erstellung von Pointer-Monikern.

Class-Monikers Obwohl Klassen mittels CoCreateInstance oder CoGetClassObject typischerweise direkt über ihre CLSID referenzierbar sind, lässt sich über einen Class-Moniker ebenfalls auf sie verweisen. Class-Moniker binden Klassenobjekte der Klasse für die sie instanziert wurden. Die Fähigkeit Klassen anhand eines Monikers zu identifizieren, erweitert die Operationen mit Moniker um die nützliche Eigenschaft Objekte direkt an die Klasse einer Anwendung zu binden. Ein Komposition aus Class- und File-Moniker ermöglicht beispielsweise die direkte Assoziation eines Charting-Objekts in einer Datei mit der in Excel implementierten Charting-Klasse. Das Erstellen eines Class-Monikers erfolgt über die API-Funktion CreateClassMoniker.

2.4.2 Running Object Table [ROT]

Die ROT ist eine rechnerbezogene öffentliche Tabelle, in der sich aktive oder laufende Instanzen von Komponenten nach Bedarf mittels eines Monikers registrieren und bei Passivität wieder austragen. Moniker Provider erhöhen grundsätzlich den Referenzzähler eines Objekts und melden es anschließend in der ROT an. Ein Objekt kann daher erst durch die abschließende Freigabe seitens des Monikers zerstört und in Folge aus der Tabelle entfernt werden. Clients können anhand der ROT einerseits die Verfügbarkeit eines laufenden Servers im Betriebssystem erfahren und andererseits über einen entsprechenden Moniker auf die bereits bestehende Instanzen zugreifen. Typischer Nutznießer dieses Konzeptes ist Word; Dokumente die es durch einen Doppelklick zu öffnen gilt, werden stets an die selbe Instanz der Textverarbeitung übermittelt. Der Zugang zur ROT-Tabelle erfolgt über die API-Funktion GetRunningObjectTable, die einen Zeiger auf IRunningObjectTable zurückgibt. Ein ROT-Beispiel einer Kommunikation mehrerer Clients mit derselben Instanz eines Servers befindet sich unter den beiliegenden Quelltexten [Samples\ROT-Server & Client].

Nächste Seite >>
2.5 Proxies und Stub als Stellvertreter
<< Vorherige Seite
2.3 Eventfähigkeit, IConnectionPoint & IConnectionPointContainer