Überlegungen zur Eigenschaftsspeicherung
IPropertyStorage::ReadMultiple- liest so viele der eigenschaften, die im rgpspec Array angegeben sind, wie im Eigenschaftensatz zu finden sind. Solange eine der angeforderten Eigenschaften gelesen wird, ist eine Anforderung zum Abrufen einer Eigenschaft, die nicht vorhanden ist, kein Fehler. Stattdessen muss dies dazu führen, dass VT_EMPTY für diese Eigenschaft in das rgvar[] Array geschrieben wird. Wenn keine der angeforderten Eigenschaften vorhanden ist, sollte die Methode S_FALSE zurückgeben und in jedem PROPVARIANT-VT_EMPTY festlegen. Wenn ein anderer Fehler zurückgegeben wird, werden keine Eigenschaftswerte abgerufen, und der Aufrufer muss sich keine Gedanken darüber machen, sie freizugeben.
Der rgpspec Parameter ist ein Array von PROPSPEC- Strukturen, die für jede Eigenschaft entweder ihren Eigenschaftsbezeichner oder, falls einer zugewiesen ist, einen Zeichenfolgenbezeichner angeben. Sie können eine Zeichenfolge einem Eigenschaftenbezeichner zuordnen, indem Sie IPropertyStorage::WritePropertyNamesaufrufen. Die Verwendung von Eigenschaftsbezeichnern ist jedoch wahrscheinlich wesentlich effizienter als die Verwendung von Zeichenfolgen.
Eigenschaften, die durch den Zeichenfolgennamen (PRSPEC_LPWSTR) angefordert werden, werden bei Eigenschaftenbezeichnern (IDs) ohne Groß-/Kleinschreibung zugeordnet, wie sie im aktuellen Eigenschaftensatz (und entsprechend dem aktuellen Systemgebietsschema) angegeben werden.
Wenn der Eigenschaftentyp VT_LPSTR und die Eigenschaft aus einem ANSI-Eigenschaftensatz gelesen wird, d. h. die Codeseite für den Eigenschaftensatz wird auf einen anderen Wert als Unicode festgelegt, der Wert der Eigenschaft verwendet dieselbe Codeseite wie der Eigenschaftensatz. Wenn eine VT_LPSTR-Eigenschaft aus einem Unicode-Eigenschaftensatz gelesen wird, verwendet der Wert der Eigenschaft die aktuelle ANSI-Standardcodeseite des Systems, d. h. die Codeseite, die von der GetACP--Funktion zurückgegeben wird.
Ein PROPVARIANT-, mit Ausnahme derEr, die Zeiger auf Datenströme und Speicher sind, wird als einfache PROPVARIANTbezeichnet. Diese einfachen PROPVARIANTDaten nach Wert empfangen, sodass ein Aufruf von IPropertyStorage::ReadMultiple eine Kopie der Daten bereitstellt, die der Aufrufer dann besitzt. Rufen Sie IPropertyStorage::WriteMultipleauf, um diese Eigenschaften zu erstellen oder zu aktualisieren.
Im Gegensatz dazu sind die Variantentypen VT_STREAM, VT_STREAMED_OBJECT, VT_STORAGE und VT_STORED_OBJECT nicht einfache Eigenschaften, da die Methode statt eines Werts einen Zeiger auf die angegebene Schnittstelle abruft, aus der die Daten dann gelesen werden können. Diese Typen ermöglichen die Speicherung großer Informationsmengen über eine einzelne Eigenschaft. Es gibt mehrere Probleme, die bei der Verwendung von Nichtimplenzeigenschaften auftreten.
Rufen Sie zum Erstellen dieser Eigenschaften wie für die anderen Eigenschaften IPropertyStorage::WriteMultipleauf. Anstatt die gleiche Methode zum Aktualisieren aufzurufen, ist es jedoch effizienter, zuerst IPropertyStorage::ReadMultiple aufzurufen, um den Schnittstellenzeiger auf den Datenstrom oder Speicher abzurufen, und dann Daten mithilfe der IStream-- oder IStorage--Methoden zu schreiben. Ein über eine Eigenschaft geöffneter Datenstrom oder Speicher wird immer im direkten Modus geöffnet, sodass keine zusätzliche Ebene der geschachtelten Transaktion eingeführt wird. Je nachdem, wie sie über IPropertySetStoragegeöffnet oder erstellt wurde, kann es jedoch dennoch eine Transaktion für die gesamte Eigenschaft geben. Darüber hinaus werden die Beim Öffnen oder Erstellen des Eigenschaftensatzes angegebenen Zugriffs- und Freigabemodustags an eigenschaftsbasierte Datenströme oder Speicher übergeben.
Die Lebensdauer von eigenschaftsbasierten Datenstrom- oder Speicherzeigern, obwohl theoretisch unabhängig von ihren zugeordneten IPropertyStorage und IPropertySetStorage Zeiger, tatsächlich, effektiv von ihnen abhängen. Die daten, die über den Datenstrom oder Speicher sichtbar sind, beziehen sich auf die Transaktion für das Eigenschaftsspeicherobjekt, aus dem sie abgerufen wird, genauso wie für ein Speicherobjekt (unterstützt IStorage) mit enthaltenen Datenstrom- und Speicherunterobjekten. Wenn die Transaktion für das übergeordnete Objekt abgebrochen wird, sind vorhandene IStream- und IStorage- untergeordneten Zeiger dieses Objekts nicht mehr zugänglich. Da IPropertyStorage die einzige Schnittstelle des Eigenschaftenspeicherobjekts ist, ist die nützliche Lebensdauer der enthaltenen IStream- und IStorage Zeiger an die Lebensdauer der IPropertyStorage Schnittstelle gebunden.
Die Implementierung muss sich auch mit der Situation befassen, in der dieselbe Stream- oder Speicherwerteigenschaft mehrmals über die gleiche IPropertyStorage Schnittstelleninstanz angefordert wird. In der COM-Verbunddateiimplementierung wird das Öffnen z. B. erfolgreich oder fehlschlagen, je nachdem, ob die Eigenschaft bereits geöffnet ist.
Ein weiteres Problem besteht darin, dass mehrere im Transaktionsmodus geöffnet werden. Das Ergebnis hängt von der Isolationsebene ab, die über einen Aufruf von IPropertySetStorage- Methoden angegeben wurde (entweder die Open oder Create-Methode, über die STGM-Flags), zum Zeitpunkt des Öffnens des Eigenschaftenspeichers.
Wenn der Aufruf zum Öffnen des Eigenschaftensatzes den Lese-/Schreibzugriff angibt, werden IStorage- und IStream--wertd-Eigenschaften immer mit Lese-/Schreibzugriff geöffnet. Daten können dann über diese Schnittstellen geschrieben werden und den Wert der Eigenschaft ändern, was die effizienteste Möglichkeit ist, diese Eigenschaften zu aktualisieren. Der Eigenschaftswert selbst verfügt nicht über eine zusätzliche Transaktionsschachtelungsebene, sodass Änderungen unter der Transaktion (sofern vorhanden) für das Eigenschaftsspeicherobjekt festgelegt werden.
Speicher- und Stream-Eigenschaften
Um ein Datenstrom- oder Speicherobjekt in einen Eigenschaftensatz zu schreiben, muss der Eigenschaftensatz als Nichtimple erstellt worden sein. Weitere Informationen zu einfachen und nichtimpleierten Eigenschaftensätzen finden Sie im Abschnitt Speicher- und Streamobjekte für einen Property Set-. Die folgenden Eigenschaftstypen, wie im feld vt des rgvar Arrayelemente angegeben, sind Datenstrom- oder Speichertypen: VT_STREAM, VT_STORAGE, VT_STREAMED_OBJECT, VT_STORED_OBJECT.
Rufen Sie IPropertyStorage::WriteMultipleauf, um ein Datenstrom- oder Speicherobjekt als Eigenschaft in einem nicht einfachen Eigenschaftensatz zu schreiben. Sie würden diese Methode auch aufrufen, um einfache Eigenschaften zu aktualisieren, es ist jedoch keine effiziente Möglichkeit, Datenstrom- und Speicherobjekte in einem Eigenschaftensatz zu aktualisieren. Dies liegt daran, dass das Aktualisieren einer dieser Eigenschaften über einen Aufruf von WriteMultiple im Eigenschaftenspeicherobjekt eine Kopie der übergebenen Daten erstellt, und die IStorage oder IStream- Zeiger werden nicht über die Dauer dieses Aufrufs hinaus beibehalten. In der Regel ist es effizienter, Datenstrom- oder Speicherobjekte direkt zu aktualisieren, indem zuerst IPropertyStorage::ReadMultiple aufgerufen wird, um den Schnittstellenzeiger auf den Datenstrom oder Speicher abzurufen, und dann Daten über die IStream-- oder IStorage--Methoden zu schreiben.
Sie können z. B. IPropertyStorage::WriteMultiple- aufrufen, um ein NULL- Stream- oder Speicherobjekt zu schreiben. Die Implementierung erstellt dann ein leeres Objekt im Eigenschaftensatz. Sie können dann zugriff auf dieses Objekt erhalten, indem Sie IPropertyStorage::ReadMultipleaufrufen. Wenn Sie mit der Aktualisierung dieses Objekts fertig sind, müssen Sie es nicht in den Eigenschaftensatz schreiben, da die Aktualisierungen direkt in den Eigenschaftensatz eingefügt wurden.
Ein über eine Eigenschaft geöffneter Datenstrom oder Speicher wird immer im direkten Modus geöffnet, sodass keine zusätzliche Ebene der geschachtelten Transaktion eingeführt wird. Möglicherweise gibt es noch eine Transaktion für die Eigenschaft, die als Ganzes festgelegt ist. (Wenn beispielsweise die IPropertyStorage durch Aufrufen von IPropertySetStorage::Open abgerufen wurde, wobei das STGM_TRANSACTED Flag im grfmode Parameter festgelegt ist.) Darüber hinaus wird ein eigenschaftsbasierter Datenstrom oder Speicher im Lese-/Schreibmodus geöffnet, sofern möglich, aufgrund des Modus für den Eigenschaftensatz; andernfalls wird der Lesemodus verwendet.
Wie bereits erwähnt, wird eine Kopie des Objekts erstellt, wenn ein Stream- oder Speicherobjekt in einen Eigenschaftensatz mit der WriteMultiple--Methode geschrieben wird. Wenn eine solche Kopie in einem Datenstromobjekt erstellt wird, beginnt der Kopiervorgang an der aktuellen Suchposition der Quelle. Die Suchposition ist nicht definiert auf Fehler, aber bei Erfolg ist sie am Ende des Datenstroms; der Suchzeiger wird nicht an seiner ursprünglichen Position wiederhergestellt.
Wenn eine Stream- oder Speichereigenschaft aus einem Eigenschaftensatz mit ReadMultiplegelesen wurde, wird weiterhin geöffnet gehalten, und ein anschließender Aufruf von WriteMultiple- für dieselbe Eigenschaft erfolgt, wird der WriteMultiple--Vorgang erfolgreich ausgeführt. Die zuvor geöffnete Datenstrom- oder Speichereigenschaft wird in den wiederhergestellten Zustand versetzt (alle Aufrufe werden STG_E_REVERTED Fehler zurückgegeben).
Wenn die WriteMultiple--Methode beim Schreiben eines Arrays von Eigenschaften oder sogar einzelne nicht einfache Eigenschaften einen Fehler zurückgibt, wird die tatsächlich geschriebene Datenmenge nicht definiert.
Referenzeigenschaften
Wenn eine angegebene PROPVARIANT- Struktur das VT_BYREF Flag in seinem vt--Element enthält, ist die zugeordnete Eigenschaft eine Referenzeigenschaft. Eine Referenzeigenschaft wird automatisch abgeleitet, bevor der Wert in den Eigenschaftensatz geschrieben wird. Wenn beispielsweise das vt Member der PROPVARIANT- Struktur einen Wert vom Typ VT_BYREF | VT_I4 ist der tatsächliche geschriebene Wert ein VT_I4 Typ. Ein nachfolgender Aufruf der IPropertyStorage::ReadMultiple--Methode gibt einen Wert als VT_I4 zurück. Die Verwendung von Referenzeigenschaften ähnelt dem Aufrufen der VariantCopyInd--Funktion. VariantCopyInd gibt die Zielvariante frei und erstellt eine Kopie der Quelle VARIANTARG, wobei die erforderliche Dereferenzierung ausgeführt wird, wenn die Quelle als VT_BYREF angegeben ist. Diese Funktion ist nützlich, wenn eine Kopie einer Variante benötigt wird, und um sicherzustellen, dass sie nicht VT_BYREF ist, z. B. beim Behandeln von Argumenten in einer Implementierung von IDispatch::Invoke.
Hinweise für Anrufer
Es wird empfohlen, Eigenschaftensätze als Unicode zu erstellen, indem das PROPSETFLAG_ANSI Flag nicht im grfFlags Parameter von IPropertySetStorage::Createfestgelegt wird. Es wird auch empfohlen, VT_LPSTR Werte zu vermeiden und stattdessen VT_LPWSTR Werte zu verwenden. Wenn die Eigenschaftensatz-Codeseite Unicode ist, werden VT_LPSTR Zeichenfolgenwerte beim Speichern in Unicode und zurück in Multibyte-Zeichenfolgenwerte konvertiert, wenn sie abgerufen werden. Wenn die Codepage des Eigenschaftensatzes nicht Unicode, Eigenschaftsnamen, VT_BSTR Zeichenfolgen und nicht einfache Eigenschaftswerte sind, werden beim Speichern in Multibyte-Zeichenfolgen konvertiert und beim Abrufen wieder in Unicode konvertiert, wobei alle die aktuelle SYSTEM-ANSI-Codeseite verwenden.
Hinweise zu Implementierungen
Beim Zuordnen eines Eigenschaftsbezeichners kann die Implementierung einen beliebigen Wert auswählen, der derzeit nicht im Eigenschaftensatz für einen Eigenschaftsbezeichner verwendet wird, sofern er nicht 0 oder 1 oder größer als 0x80000000 ist, die alle reservierten Werte sind. Der parameter propidNameFirst legt einen Mindestwert für Eigenschaftsbezeichner innerhalb des Satzes fest und muss größer als 1 und kleiner als 0x80000000 sein. Siehe Abschnitt "Hinweise" weiter oben.
Verwandte Themen