XAML-Knotendatenstromstrukturen und Konzepte
Die in .NET-XAML-Diensten implementierten XAML-Reader und XAML-Writer basieren auf dem Entwurfskonzept eines XAML-Knotenstreams. Der XAML-Knotenstream ist eine Konzeptualisierung eines Satzes von XAML-Knoten. In dieser Konzeptualisierung arbeitet ein XAML-Prozessor die Struktur der Knotenbeziehungen in der XAML einzeln ab. Dabei ist immer nur ein aktueller Datensatz oder eine aktuelle Position in einem geöffneten XAML-Knotenstream vorhanden, und viele Aspekte der APIs melden nur die von dieser Position verfügbaren Informationen. Der aktuelle Knoten in einem XAML-Knotenstream kann als Objekt, Member oder Wert beschrieben werden. Indem Sie XAML als einen XAML-Knotenstream behandeln, können XAML-Reader mit XAML-Writern kommunizieren und ein Programm aktivieren, um die Inhalte eines XAML-Knotenstreams während eines Ladepfad- oder Speicherpfadvorgangs, an dem XAML beteiligt ist, anzuzeigen, mit diesen zu interagieren oder sie zu verändern. Der API-Entwurf von XAML-Readern und -Writern und das Konzept des XAML-Knotenstreams ähneln früheren verwandten Reader- und Writerentwürfen und -konzepten, z. B. dem XAML-Dokumentobjektmodell (DOM) und den XmlReader- und XmlWriter-Klassen. In diesem Thema werden XAML-Knotenstreamkonzepte erläutert, und es wird beschrieben, wie Sie Routinen schreiben können, die mit XAML-Darstellungen auf XAML-Knotenebene interagieren.
Laden von XAML in einen XAML-Reader
Die XamlReader -Basisklasse deklariert kein bestimmtes Verfahren zum Laden der anfänglichen XAML in einen XAML-Reader. Stattdessen deklariert und implementiert eine abgeleitete Klasse die Ladetechnik, einschließlich der allgemeinen Eigenschaften und Einschränkungen der Eingabequelle für XAML. Ein XamlObjectReader liest z. B. ein Objektdiagramm beginnend mit der Eingabequelle eines einzelnen Objekts, das den Stamm oder die Basis darstellt. Anschließend erzeugt der XamlObjectReader einen XAML-Knotenstream aus dem Objektdiagramm.
Die bekannteste von .NET-XAML-Diensten definierte XamlReader -Unterklasse ist XamlXmlReader. DerXamlXmlReader lädt die anfängliche XAML, indem eine Textdatei direkt über einen Stream oder Dateipfad oder indirekt über eine zugehörige Readerklasse wie TextReadergeladen wird. Der XamlReader enthält somit die gesamte XAML-Eingabequelle, nachdem diese geladen wurde. Die XamlReader -Basis-API ist jedoch so aufgebaut, dass der Reader mit einem einzelnen Knoten der XAML interagiert. Beim erstmaligen Laden ist der erste gefundene einzelne Knoten der Stamm der XAML und das zugehörige Startobjekt.
XAML-Knotenstreamkonzept
Wenn Sie besser mit einem DOM-, strukturmetapher- oder abfragebasierten Ansatz für den Zugriff auf XML-basierte Technologien vertraut sind, ist es hilfreich, sich einen XAML-Knotenstream wie im Folgenden beschrieben vorzustellen. Stellen Sie sich vor, dass die geladene XAML ein DOM oder eine Struktur ist, in dem bzw. der jeder mögliche Knoten vollständig erweitert und anschließend linear dargestellt wird. Wenn Sie die Knoten durchlaufen, begegnen Ihnen möglicherweise Ebenen, die bei einem DOM relevant wären, vom XAML-Knotenstream aber nicht explizit verfolgt werden, weil diese Ebenenkonzepte für einen Knotenstream nicht relevant sind. Der Knotenstream hat eine "aktuelle" Position. Sofern Sie andere Teile des Streams jedoch nicht selbst als Verweise gespeichert haben, sind alle Aspekte des Knotenstreams mit Ausnahme der aktuellen Knotenposition nicht sichtbar.
Das XAML-Knotenstreamkonzept bietet den wichtigen Vorteil, dass Sie sicher sein können, dass die gesamte XAML-Darstellung verarbeitet wurde, wenn Sie den ganzen Knotenstream durchlaufen. Sie müssen sich keine Gedanken machen, dass bei einer Abfrage, einem DOM-Vorgang oder einem anderen nicht linearen Ansatz der Informationsverarbeitung ein Teil der vollständigen XAML-Darstellung übersehen wurde. Aus diesem Grund ist die Darstellung eines XAML-Knotenstreams sowohl für die Verbindung von XAML-Readern und XAML-Writern als auch die Bereitstellung eines Systems, in dem Sie Ihren eigenen, zwischen den Lese- und Schreibphasen eines XAML-Verarbeitungsvorgangs eingesetzten Prozess einfügen können, ideal geeignet. In vielen Fällen wird die Reihenfolge von Knoten im XAML-Knotenstream gegenüber der möglichen Reihenfolge im Quelltext, in der Binärdatei oder im Objektdiagramm bewusst von XAML-Readern optimiert oder neu geordnet. Durch dieses Verhalten wird eine XAML-Verarbeitungsarchitektur erzwungen, in der XAML-Writer nie im Knotenstream zurückgehen müssen. Im Idealfall sollten alle XAML-Schreibvorgänge in der Lage sein, basierend auf dem Schemakontext und der aktuellen Position des Knotenstreams zu arbeiten.
Grundlegende Leseknotenschleife
Eine grundlegende Leseknotenschleife zum Untersuchen eines XAML-Knotenstreams besteht aus den folgenden Konzepten. Bei den in diesem Thema erläuterten Knotenschleifen wird davon ausgegangen, dass Sie eine textbasierte, lesbare XAML-Datei mit XamlXmlReaderlesen. Die Links in diesem Abschnitt verweisen auf die von XamlXmlReaderimplementierte XAML-Knotenschleifen-API.
Stellen Sie sicher, dass Sie sich nicht am Ende des XAML-Knotenstreams befinden (überprüfen Sie IsEof, oder verwenden Sie den Read -Rückgabewert). Wenn Sie sich am Ende des Streams befinden, gibt es keinen aktuellen Knoten, und Sie sollten den Stream beenden.
Überprüfen Sie, welchen Knotentyp der XAML-Knotenstream gerade bereitstellt, indem Sie NodeTypeaufrufen.
Wenn Sie über einen zugehörigen, direkt verbundenen XAML-Objektwriter verfügen, rufen Sie an dieser Stelle im Allgemeinen WriteNode auf.
Verwenden Sie abhängig davon, welcher XamlNodeType als aktueller Knoten oder aktueller Datensatz gemeldet wird, einen der folgenden Aufrufe, um Informationen zum Knoteninhalt zu erhalten:
Lautet der NodeTypeStartMember oder EndMember, rufen Sie Member auf, um XamlMember -Informationen zu einem Member zu erhalten. Der Member eine XamlDirectivesein könnte, ist er nicht zwingend ein konventioneller Member mit definiertem Typ des vorherigen Objekts. Ein auf ein Objekt angewendeter
x:Name
wird z. B. als XAML-Member angezeigt, bei dem IsDirective "true" und der Name des MembersName
ist und andere Eigenschaften angeben, dass diese Direktive im XAML-Namespace der XAML-Sprache enthalten ist.Lautet der NodeTypeStartObject oder EndObject, rufen Sie Type auf, um XamlType -Informationen zu einem Objekt zu erhalten.
Lautet der NodeTypeValue, rufen Sie Valueauf. Ein Knoten ist nur ein Wert, wenn er der einfachste Ausdruck eines Werts für einen Member oder der Initialisierungstext für ein Objekt ist (dabei ist jedoch das weiter unten in diesem Thema beschriebene Typkonvertierungsverhalten zu beachten).
Lautet der NodeTypeNamespaceDeclaration, rufen Sie Namespace auf, um Namespaceinformationen für einen Namespaceknoten zu erhalten.
Rufen Sie Read auf, um den XAML-Reader auf den nächsten Knoten im XAML-Knotenstream zu setzen, und wiederholen Sie die Schritte.
Der von XAML-Readern der .NET-XAML-Dienste bereitgestellte XAML-Knotenstream stellt immer einen vollständigen, tiefen Durchlauf aller möglichen Knoten bereit. Typische Flusssteuerungstechniken für eine XAML-Knotenschleife umfassen die Definition eines Texts in while (reader.Read())
und das Aktivieren von NodeType an jedem Knotenpunkt in der Knotenschleife.
Wenn sich der Knotenstream am Dateiende befindet, ist der aktuelle Knoten null.
Das folgende Beispiel zeigt die einfachste Schleife mit einem Reader und Writer.
XamlXmlReader xxr = new XamlXmlReader(new StringReader(xamlStringToLoad));
//where xamlStringToLoad is a string of well formed XAML
XamlObjectWriter xow = new XamlObjectWriter(xxr.SchemaContext);
while (xxr.Read()) {
xow.WriteNode(xxr);
}
In diesem grundlegenden Beispiel für eine Ladepfad-XAML-Knotenschleife werden XAML-Reader und XAML-Writer verbunden. Dies entspricht der Verwendung von XamlServices.Parse. Aber diese grundlegende Struktur wird anschließend dem Lese- oder Schreibeszenario entsprechend erweitert. Im Folgenden sind einige mögliche Szenarien angegeben:
NodeTypeaktivieren. Unterschiedliche Aktionen abhängig vom gelesenen Knotentyp ausführen.
WriteNode nicht in jedem Fall aufrufen. WriteNode nur in einigen NodeType -Fällen aufrufen.
Innerhalb der Logik für einen bestimmten Knotentyp die Einzelheiten dieses Knotens analysieren und entsprechend reagieren. Zum Beispiel könnten nur Objekte geschrieben werden, die von einem bestimmten XAML-Namespace stammen, und anschließend alle Objekte ausgelassen oder zurückgestellt werden, die nicht von diesem XAML-Namespace stammen. Es könnten auch beliebige XAML-Direktiven, die das XAML-System nicht als Teil der Memberverarbeitung unterstützt, ausgelassen oder andernfalls erneut verarbeitet werden.
Ein benutzerdefiniertes XamlObjectWriter -Element definieren, von dem
Write*
-Methoden überschrieben werden und möglicherweise eine Typzuordnung ausgeführt wird, die den XAML-Schemakontext umgeht.Den XamlXmlReader mit einem nicht standardmäßigen XAML-Schemakontext erstellen, sodass benutzerdefinierte Unterschiede im XAML-Verhalten sowohl vom Reader als auch vom Writer verwendet werden.
Zugreifen auf XAML außerhalb des Knotenschleifenkonzepts
Es gibt andere Möglichkeiten als eine XAML-Knotenschleife, um mit einer XAML-Darstellung zu arbeiten. Es könnte z. B. ein XAML-Reader vorhanden sein, der einen indizierten Knoten lesen kann oder insbesondere direkt über x:Name
, über x:Uid
oder über andere Bezeichner auf Knoten zugreift. .NET-XAML-Dienste bieten keine vollständige Implementierung, sondern stellen ein vorgeschlagenes Muster über Dienste und Unterstützungstypen bereit. Weitere Informationen finden Sie unter IXamlIndexingReader und XamlNodeList.
Arbeiten mit dem aktuellen Code
Bei den meisten Szenarien mit einer XAML-Knotenschleife werden die Knoten nicht nur gelesen. In den meisten Szenarien werden aktuelle Knoten verarbeitet, und jeder Knoten wird einzeln an eine Implementierung von XamlWriterübergeben.
Im typischen Ladepfadszenario erzeugt ein XamlXmlReader einen XAML-Knotenstream. Die XAML-Knoten werden entsprechend der Logik und dem XAML-Schemakontext verarbeitet und an einen XamlObjectWriterübergeben. Anschließend integrieren Sie das resultierende Objektdiagramm in die Anwendung oder das Framework.
In einem typischen Speicherpfadszenario liest ein XamlObjectReader das Objektdiagramm, einzelne XAML-Knoten werden verarbeitet, und ein XamlXmlWriter gibt das serialisierte Ergebnis als XAML-Textdatei aus. Der wichtigste Aspekt dabei ist, dass bei beiden Pfaden und Szenarien jeweils mit genau einem XAML-Knoten gearbeitet wird und die XAML-Knoten für die standardisierte Behandlung verfügbar sind, die im XAML-Typsystem und den .NET-XAML-Dienste-APIs definiert ist.
Frames und Bereich
Eine XAML-Knotenschleife durchläuft einen XAML-Knotenstream linear. Der Knotenstream durchläuft Objekte, Member, die andere Objekte enthalten, usw. Oft ist es hilfreich, den Bereich innerhalb des XAML-Knotenstreams durch Implementieren eines Frame- und Stapelkonzepts nachzuverfolgen. Dies gilt besonders, wenn Sie den Knotenstream aktiv anpassen, währen Sie sich darin befinden. Die Frame- und Stapelunterstützung, die Sie als Teil der Knotenschleifenlogik implementieren, könnte die Bereiche StartObject
(oder GetObject
) und EndObject
zählen, während Sie eine XAML-Knotenstruktur – bei Betrachtung aus der DOM-Perspektive – nach unten durchlaufen.
Durchlaufen und Eingeben von Objektknoten
Der erste von einem XAML-Reader geöffnete Knoten in einem Knotenstream ist der Startobjektknoten des Stammobjekts. Definitionsgemäß ist dieses Objekt immer ein einzelner Objektknoten ohne Peers. In einem realen XAML-Beispiel wird das Stammobjekt so definiert, dass es über eine oder mehrere Eigenschaften verfügt, die mehrere Objekte enthalten, und diese Eigenschaften verfügen über Memberknoten. Die Memberknoten verfügen dann über mindestens einen Objektknoten oder könnten stattdessen auch in einem Wertknoten beendet werden. Das Stammobjekt definiert normalerweise XAML-Namensbereiche, die syntaktisch als Attribute im XAML-Textmarkup zugewiesen werden, aber einem Namescope
-Knotentyp in der XAML-Knotenstreamdarstellung entsprechen.
Sehen Sie sich das folgende XAML-Beispiel an (dies ist beliebige XAML, die von in .NET vorhandenen Typen nicht unterstützt wird). Angenommen, in diesem Objektmodell gilt Folgendes: FavorCollection
ist List<T>
von Favor
, Balloon
und NoiseMaker
können Favor
zugewiesen werden, die Balloon.Color
-Eigenschaft wird von einem Color
-Objekt unterstützt (ähnlich der WPF-Definition von Farben als bekannte Farbnamen), und Color
unterstützt einen Typkonverter für die Attributsyntax.
XAML-Markup | Sich ergebender XAML-Knotenstream |
---|---|
<Party |
Namespace -Knoten für Party |
xmlns="PartyXamlNamespace"> |
StartObject -Knoten für Party |
<Party.Favors> |
StartMember -Knoten für Party.Favors |
StartObject -Knoten für implizite FavorCollection |
|
StartMember -Knoten für implizite FavorCollection -Elementeigenschaft |
|
<Balloon |
StartObject -Knoten für Balloon |
Color="Red" |
StartMember -Knoten für Color Value -Knoten für Attributwertzeichenfolge "Red" EndMember für Color |
HasHelium="True" |
StartMember -Knoten für HasHelium Value -Knoten für Attributwertzeichenfolge "True" EndMember für HasHelium |
> |
EndObject für Balloon |
<NoiseMaker>Loudest</NoiseMaker> |
StartObject -Knoten für NoiseMaker StartMember -Knoten für _Initialization Value -Knoten für Initialisierungswertzeichenfolge "Loudest" EndMember -Knoten für _Initialization EndObject für NoiseMaker |
EndMember -Knoten für implizite FavorCollection -Elementeigenschaft |
|
EndObject -Knoten für implizite FavorCollection |
|
</Party.Favors> |
EndMember für Favors |
</Party> |
EndObject für Party |
Im XAML-Knotenstream wird das folgende Verhalten verwendet:
Wenn ein
Namespace
-Knoten vorhanden ist, wird er dem Stream unmittelbar vor demStartObject
hinzugefügt, von dem der XAML-Namespace mitxmlns
deklariert wurde. Werfen Sie erneut einen Blick auf die vorherige Tabelle mit der XAML und dem Beispielknotenstream. Beachten Sie, dass dieStartObject
- undNamespace
-Knoten im Vergleich zu ihren Deklarationspositionen im Textmarkup versetzt zu sein scheinen. Dies entspricht dem Verhalten, bei dem die Namespaceknoten immer vor dem Knoten angezeigt werden, für den sie im Knotenstream gelten. Dieser Entwurf begründet sich dadurch, dass die Namespaceinformationen für Objektwriter unerlässlich sind und bekannt sein müssen, bevor der Objektwriter versucht, die Typzuordnung auszuführen oder das Objekt anderweitig zu verarbeiten. Indem die XAML-Namespaceinformationen im Stream vor ihrem Anwendungsbereich platziert werden, ist es leichter, den Knotenstream immer in der dargestellten Reihenfolge zu verarbeiten.Wie bereits dargelegt, wird in den meisten realen Markupfällen zuerst mindestens ein
Namespace
-Knoten gelesen, wenn Knoten vom Start und nicht vomStartObject
des Stamms durchlaufen werden.Einem
StartObject
-Knoten kannStartMember
,Value
oder direktEndObject
folgen. Ihm folgt nie sofort ein weiteresStartObject
.Einem
StartMember
-Element kannStartObject
,Value
oder direktEndMember
folgen. Bei Membern, bei denen der Wert aus einem vorhandenen Wert des übergeordneten Objekts und nicht aus einemGetObject
stammt, das einen neuen Wert instanziieren würde, kann ihmStartObject
folgen. Ihm kann auch einNamespace
-Knoten folgen, der für ein späteresStartObject
gilt. Ihm folgt nie sofort ein weiteresStartMember
.Ein
Value
-Knoten stellt den Wert selbst dar. Es gibt kein "EndValue"-Element. Ihm kann nur einEndMember
folgen.Der XAML-Initialisierungstext des Objekts, wie er von der Konstruktion verwendet werden könnte, führt nicht zu einer Object-Value-Struktur. Stattdessen wird ein dedizierter Memberknoten für einen Member mit dem Namen
_Initialization
erstellt und dieser Memberknoten enthält die Initialisierungswertzeichenfolge. Falls vorhanden, ist_Initialization
immer der ersteStartMember
._Initialization
wird in einigen XAML-Dienst-Darstellungen möglicherweise mit dem XAML-Namensbereich der XAML-Sprache qualifiziert, um klarzustellen, dass_Initialization
keine definierte Eigenschaft in Unterstützungstypen ist.Eine Member-Wert-Kombination stellt eine Attributeinstellung des Werts dar. An der Verarbeitung dieses Werts kann ein Wertkonverter beteiligt sein, und der Wert ist eine einfache Zeichenfolge. Das wird jedoch erst ausgewertet, wenn ein XAML-Objektwriter diesen Knotenstream verarbeitet. Der XAML-Objektwriter besitzt den notwendigen XAML-Schemakontext, die Typsystemzuordnung und andere Unterstützung, die für Wertkonvertierungen benötigt wird.
Einem
EndMember
-Knoten kann einStartMember
-Knoten für einen nachfolgenden Member oder einEndObject
-Knoten für den Memberbesitzer folgen.Einem
EndObject
-Knoten kann einEndMember
-Knoten folgen. In Fällen, in denen Objekte Peers in den Elementen einer Auflistung sind, kann ihm auch einStartObject
-Knoten folgen. Ihm kann auch einNamespace
-Knoten folgen, der für ein späteresStartObject
gilt.- In dem besonderen Fall, dass ein gesamter Knotenstream geschlossen wird, folgt dem
EndObject
-Element des Stamms kein weiteres Element. Der Reader befindet sich jetzt am Dateiende, und Read gibtfalse
zurück.
- In dem besonderen Fall, dass ein gesamter Knotenstream geschlossen wird, folgt dem
Wertkonverter und der XAML-Knotenstream
Ein Wertkonverter ist ein allgemeiner Begriff für eine Markuperweiterung, einen Typkonverter (einschließlich Wertserialisierungsprogrammen) oder eine andere dedizierte Klasse, die über das XAML-Typsystem als Wertkonverter gemeldet wird. Im XAML-Knotenstream werden eine Typkonverterverwendung und eine Markuperweiterungsverwendung sehr unterschiedlich dargestellt.
Typkonverter im XAML-Knotenstream
Ein festgelegtes Attribut, das schließlich zu einer Typkonverterverwendung führt, wird im XAML-Knotenstream als Wert eines Members gemeldet. Der XAML-Knotenstream versucht nicht, ein Typkonverterinstanzobjekt zu erzeugen und den Wert an dieses Objekt zu übergeben. Zur Verwendung einer Konvertierungsimplementierung des Typkonverters muss der XAML-Schemakontext aufgerufen und zur Typzuordnung verwendet werden. Selbst die Bestimmung, welche Typkonverterklasse zum Verarbeiten des Werts verwendet werden soll, erfordert indirekt den XAML-Schemakontext. Wenn Sie den XAML-Standardschemakontext verwenden, sind diese Informationen im XAML-Typsystem verfügbar. Falls Sie die Informationen zur Typkonverterklasse auf der XAML-Knotenstreamebene vor der Verbindung mit einem XAML-Writer benötigen, können Sie sie aus den XamlMember -Informationen des festgelegten Members abrufen. Andernfalls sollte die Typkonvertereingabe im XAML-Knotenstream als einfacher Wert beibehalten werden, bis die übrigen Vorgänge, die das Typzuordnungssystem und den XAML-Schemakontext erfordern (z. B. die Objekterstellung durch einen XAML-Objektwriter), ausgeführt wurden.
Werfen Sie z. B. einen Blick auf die folgende Klassendefinitionsgliederung und die entsprechende XAML-Verwendung:
public class BoardSizeConverter : TypeConverter {
//converts from string to an int[2] by splitting on an "x" char
}
public class GameBoard {
[TypeConverter(typeof(BoardSizeConverter))]
public int[] BoardSize; //2x2 array, initialization not shown
}
<GameBoard BoardSize="8x8"/>
Eine Textdarstellung des XAML-Knotenstreams für diese Verwendung könnte folgendermaßen aussehen:
EinStartObject
-Element mit XamlType , das GameBoard
darstellt.
EinStartMember
-Element mit XamlMember , das BoardSize
darstellt.
Value
-Knoten mit Textzeichenfolge "8x8
".
EndMember
stimmt mit BoardSize
EndObject
stimmt mit GameBoard
Beachten Sie, dass es keine Typkonverterinstanz in diesem Knotenstream gibt. Sie können Typkonverterinformationen jedoch abrufen, indem Sie XamlMember.TypeConverter für den XamlMember für BoardSize
aufrufen. Wenn ein gültiger XAML-Schemakontext vorhanden ist, können Sie die Konvertermethoden auch aufrufen, indem Sie eine Instanz von ConverterInstanceabrufen.
Markuperweiterungen im XAML-Knotenstream
Eine Markuperweiterungsverwendung wird im XAML-Knotenstream als Objektknoten innerhalb eines Members gemeldet, wobei das Objekt eine Markuperweiterungsinstanz darstellt. Folglich wird eine Markuperweiterungsverwendung in der Knotenstreamdarstellung genauer dargestellt als eine Typkonverterverwendung, und sie enthält mehr Informationen. XamlMember -Informationen enthalten keine Informationen zur Markuperweiterung, da die Verwendung situationsbedingt ist und sich in jedem möglichen Markupfall ändert. Sie sind ebenso wie Typkonverter für Typen oder Member nicht dediziert oder implizit.
Markuperweiterungen werden in der Knotenstreamdarstellung auch dann als Objektknoten dargestellt, wenn die Markuperweiterungsverwendung im XAML-Textmarkup in Attributform erfolgte, was häufig der Fall ist. Markuperweiterungsverwendungen, bei denen ein explizites Objektelementformular verwendet wurde, werden auf dieselbe Weise behandelt.
Innerhalb eines Objektknotens für die Markuperweiterung sind möglicherweise Member dieser Markuperweiterung vorhanden. Die XAML-Knotenstreamdarstellung behält die Verwendung dieser Markuperweiterung bei, ganz gleich, ob es sich um eine Positionsparameterverwendung oder eine Verwendung mit expliziten benannten Parametern handelt.
Bei einer Positionsparameterverwendung enthält der XAML-Knotenstream eine durch die XAML-Sprache definierte Eigenschaft _PositionalParameters
, von der die Verwendung aufgezeichnet wird. Diese Eigenschaft ist ein generisches List<T> -Element mit Object -Einschränkung. Die Einschränkung ist ein Objekt und keine Zeichenfolge, da eine Positionsparameterverwendung u. U. geschachtelte Markuperweiterungsverwendungen enthalten könnte. Sie können die Liste durchlaufen und die Indexer für einzelne Listenwerte verwenden, um auf die Positionsparameter der Verwendung zuzugreifen.
Bei einer benannten Parameterverwendung wird jeder benannte Parameter als Memberknoten des Namens im Knotenstream dargestellt. Die Memberwerte sind nicht unbedingt Zeichenfolgen, da eine geschachtelte Markuperweiterungsverwendung vorhanden sein könnte.
DasProvideValue
-Element wird noch nicht von der Markuperweiterung aufgerufen. Es wird jedoch aufgerufen, wenn Sie einen XAML-Reader und einen XAML-Writer verbinden, sodass beim Untersuchen im Knotenstream WriteEndObject
für den Markuperweiterungsknoten aufgerufen wird. Aus diesem Grund muss im Allgemeinen derselbe XAML-Schemakontext verfügbar sein wie für die Bildung des Objektdiagramms auf dem Ladepfad. Andernfalls kann ProvideValue
in jeder Markuperweiterung Ausnahmen auslösen, da keine erwarteten Dienste verfügbar sind.
Durch XAML- und XML-Sprache definierte Member im XAML-Knotenstream
Bestimmte Member werden aufgrund von Interpretationen und Konventionen eines XAML-Readers in einem XAML-Knotenstream implementiert und nicht durch eine explizite XamlMember -Suche oder -Konstruktion. Häufig sind diese Member XAML-Direktiven. In einigen Fällen wird die Direktive durch das Lesen der XAML im XAML-Knotenstream eingefügt. Dies bedeutet, dass die Memberdirektive im ursprünglich eingegebenen XAML-Text nicht explizit angegeben wurde, der XAML-Reader die Direktive aber einfügt, um XAML-Strukturkonventionen zu entsprechen und Informationen im XAML-Knotenstream zu melden, bevor sie verloren gehen.
In der folgenden Liste sind alle Fälle aufgeführt, in denen ein XAML-Reader voraussichtlich einen XAML-Memberknoten für eine Direktive einfügt, und es wird beschrieben, wie dieser Memberknoten in den .NET-XAML-Dienstimplementierungen identifiziert wird.
Initialisierungstext für einen Objektknoten: Der Name dieses Memberknotens ist
_Initialization
. Er stellt eine XAML-Direktive dar und ist im XAML-Namespace der XAML-Sprache definiert. Eine entsprechende statische Entität kann aus Initializationabgerufen werden.Positionsparameter für eine Markuperweiterung: Der Name dieses Memberknotens ist
_PositionalParameters
, und er ist im XAML-Namespace der XAML-Sprache definiert. Er enthält immer eine generische Liste von Objekten, bei denen es sich um Positionsparameter handelt, die durch Trennung bei dem im Eingabe-XAML angegebenen,
-Trennzeichen vorab getrennt werden. Eine statische Entität für die Positionsparameterdirektive kann aus PositionalParametersabgerufen werden.Unbekannter Inhalt: Der Name dieses Memberknotens ist
_UnknownContent
. Streng genommen handelt es sich um ein XamlDirective-Element und ist im XAML-Namespace der XAML-Sprache definiert. Diese Direktive wird als Sentinel für Fälle verwendet, in denen ein XAML-Objektelement im Quell-XAML Inhalt aufweist, aber keine Inhaltseigenschaft im aktuell verfügbaren XAML-Schemakontext ermittelt werden kann. Sie können diesen Fall in einem XAML-Knotenstream erkennen, indem Sie ihn auf Member mit dem Namen_UnknownContent
prüfen. Falls keine andere Aktion in einem Ladepfad-XAML-Knotenstream ausgeführt wird, wird der standardmäßige XamlObjectWriter bei versuchtemWriteEndObject
ausgelöst, wenn der_UnknownContent
-Member für ein Objekt gefunden wird. Der standardmäßige XamlXmlWriter wird nicht ausgelöst, und der Member wird als implizit behandelt. Sie können eine statische Entität für_UnknownContent
von UnknownContentabrufen.Auflistungseigenschaft einer Auflistung:Obwohl der CLR-Unterstützungstyp einer für XAML verwendeten Auflistungsklasse normalerweise über eine dedizierte benannte Eigenschaft verfügt, die die Elemente der Auflistung enthält, ist diese Eigenschaft einem XAML-Typsystem vor der Unterstützungstypauflösung nicht bekannt. Stattdessen fügt der XAML-Knotenstream einen
Items
-Platzhalter als Member des XAML-Auflistungstyps ein. In der .NET-XAML-Dienstimplementierung lautet der Name dieser Direktive/dieses Members im Knotenstream_Items
. Eine Konstante für diese Direktive kann aus Itemsabgerufen werden.Beachten Sie, dass ein XAML-Knotenstream eine Items-Eigenschaft mit Elementen enthalten kann, die auf Grundlage der Unterstützungstypauflösung und des XAML-Schemakontexts nicht analysiert werden können. Ein auf ein Objekt angewendeter
In XML definierte Member: Die in XML definierten Member
xml:base
,xml:lang
undxml:space
werden als XAML-Direktiven mit den Namenbase
,lang
undspace
in den .NET-XAML-Dienstimplementierungen gemeldet. Der Namespace hierfür ist der XML-Namespacehttp://www.w3.org/XML/1998/namespace
. Konstanten für jedes dieser Elemente können von XamlLanguageabgerufen werden.
Knotenreihenfolge
In einigen Fällen ändert der XamlXmlReader die Reihenfolge von XAML-Knoten im XAML-Knotenstream gegenüber der Reihenfolge, in der die Knoten bei der Anzeige im Markup oder der Verarbeitung als XML angezeigt werden. Dies geschieht, damit die Knoten so sortiert werden, dass ein XamlObjectWriter den Knotenstream nur vorwärts verarbeiten kann. In den .NET-XAML-Diensten ordnet der XAML-Reader Knoten neu, anstatt diese Aufgabe dem XAML-Writer zu überlassen. Dies dient zur Leistungsoptimierung für XAML-Objektwriterconsumer des Knotenstreams.
Bestimmte Direktiven sind speziell zum Bereitstellen weiterer Informationen für die Erstellung eines Objekts aus einem Objektelement vorgesehen. Diese Direktiven sind: Initialization
, PositionalParameters
, TypeArguments
, FactoryMethod
und Arguments
. Die XAML-Reader der .NET-XAML-Dienste versuchen, diese Direktiven als erste Member im Knotenstream nach dem StartObject
eines Objekts zu platzieren. Die Gründe dafür werden im nächsten Abschnitt erläutert.
XamlObjectWriter-Verhalten und Knotenreihenfolge
DasStartObject
für einen XamlObjectWriter ist nicht notwendigerweise ein Signal für den XAML-Objektwriter, die Objektinstanz sofort zu erstellen. XAML umfasst mehrere Sprachfunktionen, bei denen ein Objekt mit zusätzlichen Eingaben initialisiert werden kann und das Erzeugen des anfänglichen Objekts nicht ausschließlich vom Aufrufen eines Konstruktors ohne Parameter abhängig ist, bevor Eigenschaften festgelegt werden. Zu diesen Funktionen zählen: XamlDeferLoadAttribute, Initialisierungstext, x:TypeArguments, Positionsparameter einer Markuperweiterung, Factorymethoden und zugehörige x:Arguments -Knoten (XAML 2009). In jedem dieser Fälle wird die tatsächliche Objekterstellung verzögert, und da der Knotenstream neu sortiert wird, kann der XAML-Objektwriter ein Verhalten verwenden, bei dem die Instanz tatsächlich jedes Mal erstellt wird, wenn ein Startmember gefunden wird, bei dem es sich nicht um eine Konstruktionsdirektive für diesen Objekttyp handelt.
GetObject
GetObject
stellt einen XAML-Knoten dar, in dem ein XAML-Objektwriter den Wert der enthaltenden Eigenschaft des Objekts abrufen soll, anstatt ein neues Objekt zu erstellen. Ein typischer Fall, in dem ein GetObject
-Knoten in einem XAML-Knotenstream vorkommt, ist ein Auflistungs- oder Wörterbuchobjekt, bei dem die enthaltende Eigenschaft im Objektmodell des Unterstützungstyps bewusst schreibgeschützt ist. In diesem Szenario wird die Auflistung oder das Wörterbuch häufig durch die Initialisierungslogik eines übergeordneten Typs erstellt und initialisiert (normalerweise leer).
Weitere Informationen
.NET Desktop feedback