XAML-Knotenstreamstrukturen und -konzepte
XAML-Reader und XAML-Autoren wie in .NET XAML Services implementiert basieren auf dem Entwurfskonzept eines XAML-Knotenstreams. Der XAML-Knotenstream ist eine Konzeptualisierung einer Gruppe von XAML-Knoten. In dieser Konzeptualisierung durchläuft ein XAML-Prozessor die Struktur der Knotenbeziehungen im XAML-Code einzeln. Zu jedem Zeitpunkt ist nur ein aktueller Datensatz oder eine aktuelle Position in einem geöffneten XAML-Knotenstream vorhanden, und viele Aspekte des API-Berichts sind nur die Informationen, die an dieser Position verfügbar sind. Der aktuelle Knoten in einem XAML-Knotendatenstrom kann als Objekt, Element oder Wert beschrieben werden. Durch die Behandlung von XAML als XAML-Knotendatenstrom können XAML-Leser mit XAML-Autoren kommunizieren und einem Programm das Anzeigen, Interagieren mit oder Ändern des Inhalts eines XAML-Knotendatenstroms während eines Ladepfads oder eines Speicherpfadvorgangs, der XAML umfasst, ermöglichen. Das XAML-Reader- und Writer-API-Design und das KONZEPT des XAML-Knotenstreams ähneln vorherigen zugehörigen Reader- und Writer-Designs und Konzepten wie dem XML-Dokumentobjektmodell (DOM) und den XmlReader- und XmlWriter-Klassen. In diesem Thema werden XAML-Knotenstreamkonzepte erläutert und beschrieben, wie Sie Routinen schreiben können, die mit XAML-Darstellungen auf XAML-Knotenebene interagieren.
Laden von XAML in einen XAML-Reader
Die Basisklasse XamlReader klasse deklariert keine bestimmte Technik zum Laden des anfänglichen XAML in einen XAML-Reader. Stattdessen deklariert und implementiert eine abgeleitete Klasse die Ladetechnik, einschließlich der allgemeinen Merkmale und Einschränkungen der Eingabequelle für XAML. Beispielsweise liest ein XamlObjectReader ein Objektdiagramm ab der Eingabequelle eines einzelnen Objekts, das den Stamm oder die Basis darstellt. Die XamlObjectReader erzeugt dann einen XAML-Knotendatenstrom aus dem Objektdiagramm.
Die prominenteste .NET XAML Services–defined XamlReader-Unterklasse ist XamlXmlReader. XamlXmlReader lädt den ursprünglichen XAML-Code, entweder durch direktes Laden einer Textdatei über einen Datenstrom oder Dateipfad oder indirekt über eine zugehörige Leseklasse wie TextReader. Der XamlReader kann man sich überlegen, wie er die gesamte XAML-Eingabequelle enthält, nachdem sie geladen wurde. Die XamlReader Basis-API ist jedoch so konzipiert, dass der Reader mit einem einzelnen Knoten des XAML-Codes interagiert. Beim ersten Laden ist der erste einzelne Knoten, den Sie treffen, der Stamm des XAML-Codes und dessen Startobjekt.
Das XAML-Knotenstreamkonzept
Wenn Sie mit einem DOM-, Strukturmetapher- oder abfragebasierten Ansatz für den Zugriff auf XML-basierte Technologien vertraut sind, ist eine hilfreiche Möglichkeit, einen XAML-Knotenstream wie folgt zu konzeptualisieren. Stellen Sie sich vor, dass es sich bei dem geladenen XAML-Code um ein DOM oder eine Struktur handelt, in der alle möglichen Knoten vollständig erweitert und dann linear dargestellt werden. Während Sie die Knoten durchlaufen, durchlaufen Sie möglicherweise "in" oder "out" von Ebenen, die für ein DOM relevant wären, aber der XAML-Knotendatenstrom verfolgt nicht explizit, da diese Ebenenkonzepte für einen Knotendatenstrom nicht relevant sind. Der Knotendatenstrom hat eine "aktuelle" Position, aber es sei denn, Sie haben andere Teile des Datenstroms selbst als Verweise gespeichert, jeder Aspekt des Knotendatenstroms, der nicht die aktuelle Knotenposition ist, nicht sichtbar.
Das XAML-Knotenstream-Konzept hat den bemerkenswerten Vorteil, dass Sie beim Durchlaufen des gesamten Knotendatenstroms sicher sind, dass Sie die gesamte XAML-Darstellung verarbeitet haben. Sie müssen sich keine Sorgen machen, dass eine Abfrage, ein DOM-Vorgang oder ein anderer nichtlinearer Ansatz zur Verarbeitung von Informationen einen Teil der vollständigen XAML-Darstellung verpasst hat. Aus diesem Grund ist die XAML-Knotenstreamdarstellung ideal für die Verbindung von XAML-Lesern und XAML-Autoren sowie für die Bereitstellung eines Systems, in dem Sie einen eigenen Prozess einfügen können, der zwischen den Lese- und Schreibphasen eines XAML-Verarbeitungsvorgangs fungiert. In vielen Fällen wird die Sortierung von Knoten im XAML-Knotendatenstrom von XAML-Lesern absichtlich optimiert oder neu angeordnet, anstatt wie die Reihenfolge im Quelltext, binären oder Objektdiagramm angezeigt werden kann. Dieses Verhalten soll eine XAML-Verarbeitungsarchitektur erzwingen, wobei XAML-Autoren niemals an einer Position sind, an der sie im Knotendatenstrom "zurück" wechseln müssen. Im Idealfall sollten alle XAML-Schreibvorgänge basierend auf dem Schemakontext und der aktuellen Position des Knotendatenstroms handeln können.
Eine einfache Leseknotenschleife
Eine grundlegende Leseknotenschleife zum Untersuchen eines XAML-Knotenstreams besteht aus den folgenden Konzepten. Für Knotenschleifen, wie in diesem Thema erläutert, gehen Sie davon aus, dass Sie eine textbasierte, lesbare XAML-Datei mit XamlXmlReaderlesen. Die Links in diesem Abschnitt beziehen sich auf die bestimmte XAML-Knotenschleifen-API, die von XamlXmlReaderimplementiert wird.
Stellen Sie sicher, dass Sie sich nicht am Ende des XAML-Knotendatenstroms befinden (überprüfen Sie IsEof, oder verwenden Sie den Read Rückgabewert). Wenn Sie sich am Ende des Datenstroms befinden, gibt es keinen aktuellen Knoten, und Sie sollten den Vorgang beenden.
Überprüfen Sie, welchen Knotentyp der XAML-Knotendatenstrom derzeit verfügbar macht, indem Sie NodeTypeaufrufen.
Wenn Sie über einen zugeordneten XAML-Objektschreiber verfügen, der direkt verbunden ist, rufen Sie in der Regel WriteNode an diesem Punkt auf.
Rufen Sie basierend darauf, welche XamlNodeType als aktueller Knoten oder aktueller Datensatz gemeldet wird, einen der folgenden Aufrufe, um Informationen zu den Knoteninhalten zu erhalten:
Rufen Sie für eine NodeType von StartMember oder EndMemberMember auf, um XamlMember Informationen zu einem Mitglied abzurufen. Das Element kann eine XamlDirectivesein und somit nicht unbedingt ein herkömmliches typdefiniertes Element des vorherigen Objekts sein. Beispielsweise wird
x:Name
auf ein Objekt angewendet als XAML-Element angezeigt, bei dem IsDirective wahr ist und der Name des ElementsName
ist, mit anderen Eigenschaften, die angeben, dass diese Direktive unter dem XAML-Sprach-XAML-Namespace liegt.Rufen Sie für eine NodeType von StartObject oder EndObjectType auf, um XamlType Informationen zu einem Objekt abzurufen.
Rufen Sie für eine NodeType von ValueValueauf. Ein Knoten ist nur dann ein Wert, wenn es sich um den einfachsten Ausdruck eines Werts für ein Element oder den Initialisierungstext für ein Objekt handelt (Sie sollten jedoch das Typkonvertierungsverhalten beachten, wie in einem bevorstehenden Abschnitt dieses Themas dokumentiert).
Rufen Sie für eine NodeType von NamespaceDeclarationNamespace auf, um Namespaceinformationen für einen Namespaceknoten abzurufen.
Rufen Sie Read auf, um den XAML-Reader zum nächsten Knoten im XAML-Knotenstream zu wechseln, und wiederholen Sie die Schritte erneut.
Der von .NET XAML Services-XAML-Readern bereitgestellte XAML-Knotenstream bietet immer eine vollständige, tiefe Traversal aller möglichen Knoten. Typische Flusssteuerungstechniken für eine XAML-Knotenschleife umfassen das Definieren eines Textkörpers innerhalb while (reader.Read())
und das Einschalten NodeType an jedem Knotenpunkt in der Knotenschleife.
Wenn sich der Knotendatenstrom am Ende der Datei befindet, ist der aktuelle Knoten null.
Die einfachste Schleife, die einen Reader und Writer verwendet, ähnelt dem folgenden Beispiel.
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);
}
Dieses grundlegende Beispiel für eine XAML-Knotenschleife für den Ladepfad verbindet transparent den XAML-Reader und XAML-Writer und führt nichts anderes aus, als wenn Sie XamlServices.Parseverwendet haben. Diese grundlegende Struktur wird dann jedoch erweitert, um sie auf Ihr Lese- oder Schreibszenario anzuwenden. Einige mögliche Szenarien sind wie folgt:
Schalten Sie NodeTypeein. Führen Sie unterschiedliche Aktionen aus, je nachdem, welcher Knotentyp gelesen wird.
Rufen Sie WriteNode in allen Fällen nicht auf. Rufen Sie in einigen NodeType Fällen nur WriteNode auf.
Analysieren Sie innerhalb der Logik für einen bestimmten Knotentyp die Besonderheiten dieses Knotens, und reagieren Sie darauf. Sie können beispielsweise nur Objekte schreiben, die aus einem bestimmten XAML-Namespace stammen, und dann objekte ablegen oder zurückstellen, die nicht aus diesem XAML-Namespace stammen. Sie können auch alle XAML-Direktiven ablegen oder anderweitig verarbeiten, die ihr XAML-System im Rahmen der Memberverarbeitung nicht unterstützt.
Definieren Sie eine benutzerdefinierte XamlObjectWriter, die
Write*
Methoden außer Kraft setzt und möglicherweise eine Typzuordnung durchführt, die den XAML-Schemakontext umgeht.Erstellen Sie die XamlXmlReader, um einen nicht standardmäßigen XAML-Schemakontext zu verwenden, sodass benutzerdefinierte Unterschiede im XAML-Verhalten sowohl vom Leser als auch vom Writer verwendet werden.
Zugreifen auf XAML über das Knotenschleifenkonzept hinaus
Es gibt potenziell andere Möglichkeiten, mit einer anderen XAML-Darstellung als einer XAML-Knotenschleife zu arbeiten. Beispielsweise könnte ein XAML-Reader vorhanden sein, der einen indizierten Knoten lesen kann oder insbesondere direkt über x:Name
, durch x:Uid
oder über andere Bezeichner auf Knoten zugreift. .NET XAML Services stellt keine vollständige Implementierung bereit, sondern stellt ein vorgeschlagenes Muster über Dienste und Supporttypen bereit. Weitere Informationen finden Sie unter IXamlIndexingReader und XamlNodeList.
Arbeiten mit dem aktuellen Knoten
Die meisten Szenarien, in denen eine XAML-Knotenschleife verwendet wird, lesen nicht nur die Knoten. Die meisten Szenarien verarbeiten aktuelle Knoten und übergeben jeden Knoten einzeln an eine Implementierung von XamlWriter.
Im typischen Ladepfadszenario erzeugt ein XamlXmlReader einen XAML-Knotendatenstrom; die XAML-Knoten werden gemäß Ihrer Logik und ihrem XAML-Schemakontext verarbeitet; und die Knoten werden an eine XamlObjectWriterübergeben. Anschließend integrieren Sie das resultierende Objektdiagramm in Ihre 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 Schlüssel besteht darin, dass sowohl Pfade als auch Szenarien das Gleichzeitige Arbeiten mit genau einem XAML-Knoten umfassen, und die XAML-Knoten stehen für die Behandlung auf standardisierte Weise zur Verfügung, die vom XAML-Typsystem und the.NET XAML-Dienste-APIs definiert wird.
Frames und Bereich
Eine XAML-Knotenschleife durchläuft einen XAML-Knotendatenstrom linear. Der Knotendatenstrom durchläuft objekte, in Elemente, die andere Objekte enthalten usw. Es ist häufig hilfreich, den Bereich innerhalb des XAML-Knotendatenstroms nachzuverfolgen, indem ein Frame- und Stapelkonzept implementiert wird. Dies gilt insbesondere, wenn Sie den Knotendatenstrom aktiv anpassen, während Sie sich darin befinden. Die Frame- und Stack-Unterstützung, die Sie als Teil der Knotenschleifenlogik implementieren, kann StartObject
(oder GetObject
) und EndObject
Bereiche zählen, während Sie in eine XAML-Knotenstruktur absteigen, wenn die Struktur aus DOM-Perspektive betrachtet wird.
Durchlaufen und Eingeben von Objektknoten
Der erste Knoten in einem Knotendatenstrom, wenn er von einem XAML-Reader geöffnet wird, ist der Startobjektknoten des Stammobjekts. Standardmäßig ist dieses Objekt immer ein einzelner Objektknoten und hat keine Peers. In jedem realen XAML-Beispiel wird das Stammobjekt definiert, um eine oder mehrere Eigenschaften zu haben, die mehr Objekte enthalten, und diese Eigenschaften weisen Memberknoten auf. Die Memberknoten verfügen dann über einen oder mehrere Objektknoten oder können stattdessen in einem Wertknoten beendet werden. Das Stammobjekt definiert in der Regel XAML-NameScopes, die syntaktisch als Attribute im XAML-Textmarkup zugewiesen werden, aber einem Namescope
Knotentyp in der XAML-Knotenstreamdarstellung zugeordnet sind.
Betrachten Sie das folgende XAML-Beispiel (dies ist beliebiges XAML, nicht durch vorhandene Typen in .NET gesichert). Gehen Sie davon aus, dass FavorCollection
in diesem Objektmodell List<T>
von Favor
ist, Balloon
und NoiseMaker
Favor
zuweisen können, wird die Balloon.Color
-Eigenschaft durch ein Color
Objekt unterstützt, das der Definition von Farben als bekannte Farbnamen ähnelt, und Color
einen Typkonverter für die Attributsyntax unterstützt.
XAML-Markup | Resultierender XAML-Knotendatenstrom |
---|---|
<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 Items-Eigenschaft. |
|
<Balloon |
StartObject Knoten für Balloon |
Color="Red" |
StartMember Knoten für Color Value Knoten für die Attributwertzeichenfolge "Red" EndMember für Color |
HasHelium="True" |
StartMember Knoten für HasHelium Value Knoten für die 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 die Initialisierungswertzeichenfolge "Loudest" EndMember Knoten für _Initialization EndObject für NoiseMaker |
EndMember Knoten für implizite FavorCollection Items-Eigenschaft. |
|
EndObject Knoten für implizite FavorCollection |
|
</Party.Favors> |
EndMember für Favors |
</Party> |
EndObject für Party |
Im XAML-Knotendatenstrom können Sie sich auf das folgende Verhalten verlassen:
Wenn ein
Namespace
Knoten vorhanden ist, wird er dem Datenstrom unmittelbar vor demStartObject
hinzugefügt, der den XAML-Namespace mitxmlns
deklariert hat. Sehen Sie sich die vorherige Tabelle mit dem XAML- und Beispielknotendatenstrom erneut an. Beachten Sie, wie dieStartObject
undNamespace
Knoten im Vergleich zu ihren Deklarationspositionen im Textmarkup transponiert werden scheinen. Dies ist repräsentativ für das Verhalten, bei dem die Namespaceknoten immer vor dem Knoten angezeigt werden, auf den sie im Knotenstream angewendet werden. Der Zweck dieses Designs besteht darin, dass die Namespaceinformationen für Objektautoren von entscheidender Bedeutung sind und bekannt sein müssen, bevor der Objektschreiber versucht, die Typzuordnung durchzuführen oder das Objekt anderweitig zu verarbeiten. Durch das Platzieren der XAML-Namespaceinformationen vor dem Anwendungsumfang im Datenstrom ist es einfacher, den Knotendatenstrom in seiner dargestellten Reihenfolge immer zu verarbeiten.Aufgrund der vorstehenden Überlegungen ist es ein oder mehrere
Namespace
Knoten, die Sie zuerst in den meisten realen Markupfällen lesen, wenn Sie Knoten von Anfang an durchlaufen, nicht dieStartObject
des Stamms.Auf einen
StartObject
Knoten kannStartMember
,Value
oder eine sofortigeEndObject
folgen. Es wird nie sofort von einem anderenStartObject
gefolgt.Auf eine
StartMember
kann einStartObject
,Value
oder eine sofortigeEndMember
folgen. Es kann vonGetObject
gefolgt werden, für Elemente, bei denen der Wert von einem vorhandenen Wert des übergeordneten Objekts stammen soll, anstatt von einerStartObject
, die einen neuen Wert instanziieren würde. Es kann auch von einemNamespace
Knoten gefolgt werden, der für eine bevorstehendeStartObject
gilt. Es wird nie sofort von einem anderenStartMember
gefolgt.Ein
Value
Knoten stellt den Wert selbst dar; es gibt keinen "EndValue". Es kann nur von einerEndMember
gefolgt werden.XAML-Initialisierungstext des Objekts, wie es durch die Konstruktion verwendet werden kann, führt nicht zu einer Object-Value Struktur. Stattdessen wird ein dedizierter Memberknoten für ein Mitglied mit dem Namen
_Initialization
erstellt. und dieser Memberknoten enthält die Initialisierungswertzeichenfolge. Wenn es vorhanden ist, ist_Initialization
immer der ersteStartMember
._Initialization
können in einigen XAML-Dienstdarstellungen mit dem XAML-Sprach-XAML-NameScope qualifiziert werden, um zu verdeutlichen, dass_Initialization
keine definierte Eigenschaft in Sicherungstypen ist.Eine Member-Value Kombination stellt eine Attributeinstellung des Werts dar. Möglicherweise ist ein Wertkonverter an der Verarbeitung dieses Werts beteiligt, und der Wert ist eine einfache Zeichenfolge. Dies wird jedoch erst ausgewertet, wenn ein XAML-Objektschreiber diesen Knotendatenstrom verarbeitet. Der XAML-Objektschreiber verfügt über den erforderlichen XAML-Schemakontext, die Typsystemzuordnung und andere Unterstützung für Wertkonvertierungen.
Auf einen
EndMember
Knoten kann einStartMember
Knoten für ein nachfolgendes Mitglied oder einenEndObject
Knoten für den Memberbesitzer folgen.Auf einen
EndObject
Knoten kann einEndMember
Knoten folgen. Sie kann auch von einemStartObject
Knoten für Fälle gefolgt werden, in denen die Objekte Peers in den Elementen einer Auflistung sind. Oder es kann von einemNamespace
Knoten gefolgt werden, der für eine bevorstehendeStartObject
gilt.- Für den eindeutigen Fall, den gesamten Knotendatenstrom zu schließen, wird der
EndObject
des Stamms nicht gefolgt; der Reader ist jetzt end-of-file, und Read gibtfalse
zurück.
- Für den eindeutigen Fall, den gesamten Knotendatenstrom zu schließen, wird der
Wertkonverter und der XAML-Knotenstream
Ein Wertkonverter ist ein allgemeiner Begriff für eine Markuperweiterung, einen Typkonverter (einschließlich Wert serialisierer) oder eine andere dedizierte Klasse, die über das XAML-Typsystem als Wertkonverter gemeldet wird. Im XAML-Knotendatenstrom weisen eine Typkonverterverwendung und eine Markuperweiterungsverwendung sehr unterschiedliche Darstellungen auf.
Typkonverter im XAML-Knotenstream
Ein Attributsatz, der letztendlich zu einer Typkonverterverwendung führt, wird im XAML-Knotendatenstrom als Wert eines Elements gemeldet. Der XAML-Knotendatenstrom versucht nicht, ein Typkonverterinstanzobjekt zu erstellen und den Wert an ihn zu übergeben. Für die Verwendung der Konvertierungsimplementierung eines Typkonverters ist das Aufrufen des XAML-Schemakontexts und die Verwendung für die Typzuordnung erforderlich. Auch die Bestimmung, welche Typkonverterklasse für die Verarbeitung des Werts verwendet werden soll, erfordert indirekt den XAML-Schemakontext. Wenn Sie den standardmäßigen XAML-Schemakontext verwenden, stehen diese Informationen aus dem XAML-Typsystem zur Verfügung. Wenn Sie die Typkonverterklasseninformationen auf der EBENE des XAML-Knotenstreams benötigen, bevor Sie eine Verbindung mit einem XAML-Writer herstellen, können Sie sie aus den XamlMember Informationen des festzulegenden Elements abrufen. Andernfalls sollte die Typkonvertereingabe im XAML-Knotendatenstrom als einfacher Wert beibehalten werden, bis der rest der Vorgänge, für die das Typzuordnungssystem und der XAML-Schemakontext erforderlich sind, ausgeführt werden, z. B. die Objekterstellung durch einen XAML-Objektschreiber.
Betrachten Sie beispielsweise die folgende Klassendefinitionsgliederung und XAML-Verwendung dafür:
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-Knotendatenstroms für diese Verwendung kann wie folgt ausgedrückt werden:
StartObject
mit XamlType, die GameBoard
StartMember
mit XamlMember, die BoardSize
Value
Knoten mit Textzeichenfolge "8x8
"
EndMember
übereinstimmungen BoardSize
EndObject
übereinstimmungen GameBoard
Beachten Sie, dass in diesem Knotenstream keine Typkonverterinstanz vorhanden ist. Sie können jedoch Typkonverterinformationen abrufen, indem Sie XamlMember.TypeConverter für die XamlMember für BoardSize
aufrufen. Wenn Sie über einen gültigen XAML-Schemakontext verfügen, 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 Elements gemeldet, wobei das Objekt eine Markuperweiterungsinstanz darstellt. Daher wird eine Markuperweiterungsverwendung in der Knotendatenstromdarstellung expliziter dargestellt, als eine Typkonverterverwendung ist, und enthält weitere Informationen. XamlMember Informationen konnten Ihnen nichts über die Markuperweiterung gesagt haben, da die Verwendung situational ist und in jedem möglichen Markupfall variiert; es ist nicht dediziert und implizit pro Typ oder Element wie bei Typkonvertern.
Die Knotendatenstromdarstellung von Markuperweiterungen als Objektknoten ist der Fall, auch wenn die Verwendung der Markuperweiterung in Attributform im XAML-Textmarkup vorgenommen wurde (was häufig der Fall ist). Markuperweiterungsverwendungen, die ein explizites Objektelementformular verwendet haben, werden auf die gleiche Weise behandelt.
Innerhalb eines Markuperweiterungsobjektknotens können Elemente dieser Markuperweiterung vorhanden sein. Die XAML-Knotenstreamdarstellung behält die Verwendung dieser Markuperweiterung bei, unabhängig davon, ob es sich um eine Positionsparameterverwendung oder eine Verwendung mit expliziten benannten Parametern handelt.
Bei einer Positionsparameterverwendung enthält der XAML-Knotendatenstrom eine sprachdefinierte XAML-Eigenschaft _PositionalParameters
, die die Verwendung aufzeichnet. Diese Eigenschaft ist eine generische List<T> mit Object Einschränkung. Die Einschränkung ist Objekt und keine Zeichenfolge, da eine verwendung von positionsbezogenen Parametern darin geschachtelte Markuperweiterungsverwendungen enthalten könnte. Um auf die Positionsparameter aus der Verwendung zuzugreifen, können Sie die Liste durchlaufen und die Indexer für einzelne Listenwerte verwenden.
Bei einer benannten Parameterverwendung wird jeder benannte Parameter als Memberknoten dieses Namens im Knotendatenstrom dargestellt. Die Memberwerte sind nicht unbedingt Zeichenfolgen, da eine geschachtelte Markuperweiterungsverwendung vorhanden sein könnte.
ProvideValue
aus der Markuperweiterung wird noch nicht aufgerufen. Es wird jedoch aufgerufen, wenn Sie einen XAML-Reader und EINEN XAML-Writer verbinden, damit WriteEndObject
beim Untersuchen im Knotendatenstrom auf dem Markuperweiterungsknoten aufgerufen wird. Aus diesem Grund benötigen Sie in der Regel den gleichen XAML-Schemakontext, der verwendet werden würde, um das Objektdiagramm im Ladepfad zu bilden. Andernfalls können ProvideValue
aus jeder Markuperweiterung Ausnahmen auslösen, da sie keine erwarteten Dienste zur Verfügung hat.
XAML- und XML-Language-Defined-Elemente im XAML-Knotenstream
Bestimmte Member werden aufgrund von Interpretationen und Konventionen eines XAML-Readers in einen XAML-Knotendatenstrom eingeführt, anstatt durch eine explizite XamlMember Nachschlage- oder Konstruktion. Häufig sind diese Member XAML-Direktiven. In einigen Fällen handelt es sich um das Lesen des XAML-Codes, das die Direktive in den XAML-Knotenstream einführt. Mit anderen Worten, der ursprüngliche Eingabe-XAML-Text hat die Memberdirektive nicht explizit angegeben, aber der XAML-Reader fügt die Direktive ein, um eine strukturelle XAML-Konvention zu erfüllen und Informationen im XAML-Knotenstream zu melden, bevor diese Informationen verloren gehen.
In der folgenden Liste werden alle Fälle aufgeführt, in denen erwartet wird, dass ein XAML-Reader einen XAML-Direktive-Memberknoten einführen und wie dieser Memberknoten in .NET XAML Services-Implementierungen identifiziert wird.
Initialisierungstext für einen Objektknoten: Der Name dieses Memberknotens ist
_Initialization
, stellt sie eine XAML-Direktive dar und wird im XAML-Sprach-XAML-Namespace definiert. Sie können eine statische Entität dafür aus Initializationabrufen.Positionsparameter für eine Markuperweiterung: Der Name dieses Memberknotens ist
_PositionalParameters
und wird im XAML-Sprach-XAML-Namespace definiert. Sie enthält immer eine generische Liste von Objekten, von denen jeder ein Positionsparameter ist, der durch die Aufteilung auf das,
Trennzeichen getrennt ist, wie im Eingabe-XAML angegeben. Sie können eine statische Entität für die Positionparameterdirektive aus PositionalParametersabrufen.Unbekannter Inhalt: Der Name dieses Memberknotens ist
_UnknownContent
. Streng genommen handelt es sich um eine XamlDirective, die im XAML-Sprach-XAML-Namespace definiert ist. Diese Direktive wird als Sentinel für Fälle verwendet, in denen ein XAML-Objektelement Inhalte im XAML-Quell-XAML enthält, aber keine Inhaltseigenschaft unter dem derzeit verfügbaren XAML-Schemakontext bestimmt werden kann. Sie können diesen Fall in einem XAML-Knotendatenstrom erkennen, indem Sie nach Elementen mit dem Namen_UnknownContent
suchen. Wenn in einem XAML-Knotendatenstrom für den Ladepfad keine andere Aktion ausgeführt wird, wird die standardeinstellung XamlObjectWriter auf versuchtenWriteEndObject
ausgelöst, wenn das element_UnknownContent
in einem objekt gefunden wird. Der StandardXamlXmlWriter wird nicht ausgelöst und behandelt das Element als implizit. Sie können eine statische Entität für_UnknownContent
aus UnknownContentabrufen.Collection-Eigenschaft einer Auflistung: Obwohl der zugrunde gehende CLR-Typ einer Sammlungsklasse, die für XAML verwendet wird, normalerweise über eine dedizierte benannte Eigenschaft verfügt, die die Sammlungselemente enthält, ist diese Eigenschaft vor der Sicherungstypauflösung nicht bekannt. Stattdessen führt der XAML-Knotendatenstrom einen
Items
Platzhalter als Element des XAML-Typs der Auflistung ein. In der .NET XAML Services-Implementierung wird der Name dieser Direktive oder dieses Mitglieds im Knotendatenstrom_Items
. Eine Konstante für diese Direktive kann aus Itemsabgerufen werden.Beachten Sie, dass ein XAML-Knotendatenstrom möglicherweise eine Items-Eigenschaft mit Elementen enthält, die basierend auf der Zugrundelegungstypauflösung und dem XAML-Schemakontext nicht analysiert werden können. Zum Beispiel
XML-definierten Member: Die XML-definierten
xml:base
,xml:lang
undxml:space
Member werden als XAML-Direktiven mit dem Namenbase
,lang
undspace
in .NET XAML Services-Implementierungen gemeldet. Der Namespace für diese ist der XML-Namespacehttp://www.w3.org/XML/1998/namespace
. Konstanten für jede dieser Konstanten können aus XamlLanguageabgerufen werden.
Knotenreihenfolge
In einigen Fällen ändert XamlXmlReader die Reihenfolge der XAML-Knoten im XAML-Knotendatenstrom und die Reihenfolge, in der die Knoten angezeigt werden, wenn sie im Markup angezeigt werden oder als XML verarbeitet werden. Dies geschieht, um die Knoten so zu ordnen, dass ein XamlObjectWriter den Knotendatenstrom vorwärts verarbeiten kann. In .NET XAML Services ordnet der XAML-Reader Knoten neu an, anstatt diese Aufgabe dem XAML-Writer zu überlassen, als Leistungsoptimierung für XAML-Objektschreiber-Consumer des Knotendatenstroms.
Bestimmte Direktiven sollen speziell weitere Informationen für die Erstellung eines Objekts aus einem Objektelement bereitstellen. Diese Richtlinien sind: Initialization
, PositionalParameters
, TypeArguments
, FactoryMethod
, Arguments
. .NET XAML Services-XAML-Reader versuchen, diese Direktiven als erste Member im Knotendatenstrom nach dem StartObject
eines Objekts zu platzieren, aus Gründen, die im nächsten Abschnitt erläutert werden.
XamlObjectWriter-Verhalten und Knotenreihenfolge
StartObject
einer XamlObjectWriter ist nicht unbedingt ein Signal für den XAML-Objektschreiber, die Objektinstanz sofort zu konstruieren. XAML enthält mehrere Sprachfeatures, die es ermöglichen, ein Objekt mit zusätzlicher Eingabe zu initialisieren, und sich nicht vollständig auf das Aufrufen eines parameterlosen Konstruktors zu verlassen, um das anfängliche Objekt zu erzeugen, und nur dann Eigenschaften festlegen. Zu diesen Features gehören: XamlDeferLoadAttribute; Initialisierungstext; x:TypeArguments; Positionsparameter einer Markuperweiterung; Factorymethoden und zugeordnete x:Arguments Knoten (XAML 2009). In jedem dieser Fälle wird die eigentliche Objektkonstruktion verzögert, und da der Knotendatenstrom neu angeordnet ist, kann der XAML-Objektschreiber auf ein Verhalten angewiesen werden, das die Instanz tatsächlich erstellt, wenn ein Startelement auftritt, das nicht speziell eine Konstruktionsdirektive für diesen Objekttyp ist.
GetObject
GetObject
stellt einen XAML-Knoten dar, bei dem anstatt ein neues Objekt zu erstellen, sollte ein XAML-Objektschreiber stattdessen den Wert der enthaltenden Eigenschaft des Objekts abrufen. Ein typischer Fall, in dem ein GetObject
Knoten in einem XAML-Knotendatenstrom für ein Auflistungsobjekt oder ein Wörterbuchobjekt auftritt, wenn die enthaltende Eigenschaft im Objektmodell des Sicherungstyps absichtlich schreibgeschützt ist. In diesem Szenario wird die Auflistung oder das Wörterbuch häufig durch die Initialisierungslogik eines eigenen Typs erstellt und initialisiert (in der Regel leer).
Siehe auch
.NET Desktop feedback