XAML ノード ストリームの構造と概念について

.NET Framework XAML サービスで実装される XAML リーダーと XAML ライターは、XAML ノード ストリームの設計概念に基づいています。 XAML ノード ストリームとは、XAML ノード セットを概念化したものです。 この概念では、XAML プロセッサが XAML のノード関係の構造を 1 つずつ走査します。 どの時点でも、開いている XAML ノード ストリーム内には、現在のレコードまたは現在の位置が 1 つだけ存在し、API の多くの要素はその位置で入手できる情報のみを報告します。 XAML ノード ストリームの現在のノードは、オブジェクト、メンバー、または値です。 XAML を XAML ノード ストリームとして扱うことにより、XAML リーダーは XAML ライターと通信し、プログラムで XAML に関する読み込みパスまたは保存パス操作の間に XAML ノード ストリームのコンテンツの表示、相互作用、または変更を行うことができるようになります。 XAML リーダーおよび XAML ライターの API デザインと XAML ノード ストリームの概念は、XML Document Object Model (DOM) や、XmlReader クラスと XmlWriter クラスなど、関連する以前のリーダーおよびライターの設計と概念に似ています。 このトピックでは、XAML ノード ストリームの概念について解説し、XAML ノード レベルで XAML 表現と相互作用するルーチンを記述する方法について説明します。

このトピックは、次のセクションで構成されています。

  • XAML リーダーへの XAML の読み込み
  • 基本的な読み込みノード ループ
  • 現在のノードの使用
  • オブジェクト ノードの走査および入力
  • 値コンバーターと XAML ノード ストリーム
  • XAML ノード ストリームの XAML および XML 言語で定義されたメンバー
  • ノードの順序
  • 関連トピック

XAML リーダーへの XAML の読み込み

基本的な XamlReader クラスでは、元の XAML を XAML リーダーに読み込むための特定の方法を宣言しません。 代わりに、派生クラスが読み込み手法 (XAML の入力ソースの一般的な特性と制約など) を宣言して実装します。 たとえば、XamlObjectReader は、ルートまたはベースを表す単一オブジェクトの入力ソースから順に、オブジェクト グラフを読み取ります。 その後で、XamlObjectReader はオブジェクト グラフから XAML ノード ストリームを生成します。

.NET Framework XAML サービスで定義された最も重要な XamlReader サブクラスは、XamlXmlReader です。 XamlXmlReader は、ストリームまたはファイル パスを通じてテキスト ファイルを直接読み込むか、TextReader などの関連するリーダー クラスを通じて間接的に読み込むことで、元の XAML を読み込みます。 XamlReader には、読み込んだ後の XAML 入力ソース全体が含まれていると見なすことができます。 ただし、XamlReader の基本 API は、リーダーは XAML の単一ノードと相互作用するよう設計されています。 初回読み込み時に、最初に検出された単一ノードが XAML のルートおよび開始オブジェクトになります。

XAML ノード ストリームの概念

XML ベースのテクノロジを利用するための DOM、ツリー メタファー、またはクエリ ベースのアプローチに精通している場合は、XAML ノード ストリームを概念として理解するうえで次の方法が役立ちます。 読み込まれた XAML は、すべてのノードが完全に展開され、直線的に表示された DOM またはツリーであるとイメージしてください。 ノードを先に進むと、DOM に相当するレベルを内側または外側から走査することになりますが、XAML ノード ストリームはトラックを明示的には保持しません。これらのレベルの概念はノード ストリームには当てはまらないためです。 ノード ストリームには "現在の" 位置があるものの、ストリームの他の部分を参照として保存していない限り、現在のノード位置を除いてノード ストリームの要素を特定できません。

XAML ノード ストリームの概念には、特筆すべき利点があります。それは、ノード ストリーム全体を処理する場合、XAML 表現全体を確実に処理できる点です。つまり、クエリや DOM 操作をはじめとする非直線的な情報処理アプローチのように、XAML 表現の一部が処理されなかったのではないかという心配は無用です。 そのため、XAML ノード ストリームによる表現は、XAML リーダーと XAML ライターを接続するうえでも、XAML 処理操作の読み取りフェーズと書き込みフェーズの間で機能する独自プロセスを挿入できるシステムを構築するうえでも、理想的なアプローチです。 多くの場合、XAML ノード ストリーム内のノードの順序は、ソース テキスト、バイナリ、またはオブジェクト グラフでの順序に対して、XAML リーダーによって慎重に最適化または変更されます。 この動作の目的は、XAML ライターがノード ストリーム内で "戻る" 必要のある位置に来ないような XAML 処理アーキテクチャを適用することにあります。 すべての XAML 書き込み操作がスキーマ コンテキストとノード ストリームの現在の位置に基づいて機能するというのが理想です。

基本的な読み込みノード ループ

XAML ノード ストリームを調べるための基本的な読み込みノード ループは、次の概念によって構成されています。 このトピックで解説したノード ループの目的上、XamlXmlReader を使用して、人間が判読できるテキスト ベースの XAML ファイルを読み取ることを想定します。 このセクションのリンクは、XamlXmlReader によって実装された特定の XAML ノード ループ API を参照します。

  • XAML ノード ストリームの末尾でないことを確認してください (IsEof を確認するか、Read() の戻り値を使用します)。 ストリームの末尾である場合は現在のノードがないので、終了する必要があります。

  • NodeType を呼び出し、XAML ノード ストリームが現在公開しているノードの型を確認します。

  • 直接接続される、関連付けられている XAML オブジェクト ライターを使用している場合、通常はこの時点で WriteNode を呼び出します。

  • 現在のノードまたは現在のレコードとして報告されている XamlNodeType に基づき、次のいずれかを呼び出してノード コンテンツに関する情報を取得します。

    • StartMember または EndMemberNodeType については、Member を呼び出してメンバーに関する XamlMember の情報を取得します。 メンバーは XamlDirective である可能性があるため、前のオブジェクトの、型が定義された従来のメンバーであるとは限りません。 たとえば、オブジェクトに適用された x:Name は、IsDirective が true でメンバーの Name が Name である XAML メンバーとして表示されます。また、他のプロパティにより、このディレクティブは XAML 言語の XAML 名前空間に含まれることが示されます。

    • StartObject または EndObjectNodeType については、Type を呼び出してオブジェクトに関する XamlType の情報を取得します。

    • ValueNodeType については、Value を呼び出します。 ノードは、メンバーの値の最もシンプルな式であるか、オブジェクトの初期化テキストである場合にのみ、値となります (ただし、後で説明する型変換動作に注意する必要があります)。

    • NamespaceDeclarationNodeType の場合は、Namespace を呼び出して名前空間ノードの名前空間情報を取得します。

  • Read を呼び出し、XAML リーダーを XAML ノード ストリーム内で次のノードに進め、手順を繰り返します。

.NET Framework XAML サービスの XAML リーダーによって示される XAML ノード ストリームは、可能なすべてのノードの完全な詳細走査を指定します。 XAML ノード ループの一般的なフロー制御手法には、while (reader.Read()) 内で本体を定義することや、ノード ループ内の各ノード ポイントで NodeType をオンにすることなどがあります。

ノード ストリームがファイルの終端に達すると、現在のノードは null になります。

リーダーとライターを使用する最も単純なループは次のようになります。

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);
}

この読み込みパスの基本的な例では、XAML ノード ループは XAML リーダーおよび XAML ライターに透過的に接続するため、XamlServices.Parse を使用した場合と異なる処理は行われません。 ただし、この基本的な構造を拡張して、読み取りおよび書き込みのシナリオに適用します。 考えられるシナリオを次に示します。

  • NodeType をオンにします。 読み取る対象のノード型に応じて異なるアクションを実行します。

  • WriteNode を呼び出すケースは限られています。 一部の NodeType のケースでのみ、WriteNode を呼び出してください。

  • 特定のノード型のロジックでは、そのノードの詳細を分析して操作します。 たとえば、書き込みできるオブジェクトが特定の XAML 名前空間から派生したオブジェクトに限定される場合、XAML 名前空間から派生していないオブジェクトに対しては無効化または保留を実行できます。 または、XAML システムでメンバー処理の一部としてサポートされていない XAML ディレクティブを無効化または再処理できます。

  • 場合によっては、XAML スキーマ コンテキストをバイパスして型マッピングを実行する、Write* メソッドを無視するカスタム XamlObjectWriter を定義します。

  • 既定以外の XAML スキーマ コンテキストを使用するように XamlXmlReader を構築し、カスタマイズされた XAML 動作がリーダーとライターの両方で使用されるようにします。

ノード ループ概念外の XAML へのアクセス

XAML ノード ループとして以外にも、XAML 表現を使用する方法が他にもあります。 たとえば、インデックス付きノードを読み込むことができる XAML リーダーや、特に x:Name、x:Uid、または他の識別子を使用し、ノードに直接アクセスできる XAML リーダーもある可能性もあります。 .NET Framework XAML サービスでは完全な実装を示しませんが、サービスやサポート型によって、パターンを示します。 詳細については、「IXamlIndexingReader」および「XamlNodeList」を参照してください。

ヒントヒント

マイクロソフトでは、Microsoft XAML Toolkit と呼ばれる特別なリリースも提供しています。この特別なリリースは、まだプレリリースの段階にあります。ただし、プレリリース コンポーネントを利用すると、XAML ツーリングと XAML のスタティック分析に対応した、Microsoft XAML Toolkit の魅力的なリソースを使用できます。Microsoft XAML Toolkit には、XAML DOM API、FxCop 分析のサポート、および Silverlight 用の XAML スキーマ コンテキストが含まれています。詳細については、「Microsoft XAML Toolkit」を参照してください。

現在のノードの使用

XAML ノード ループを使用するシナリオの大半は、ノードを読み取るだけではありません。 ほとんどのシナリオでは、現在のノードを処理し、各ノードを 1 つずつ XamlWriter の実装に渡します。

一般的な読み込みパスのシナリオでは、XamlXmlReader が XAML ノード ストリームを生成し、XAML ノードは各自のロジックおよび XAML スキーマ コンテキストに基づいて処理された後、XamlObjectWriter に渡されます。 その後、生成されるオブジェクト グラフをアプリケーションまたはフレームワークに統合します。

一般的な保存パスのシナリオでは、XamlObjectReader がオブジェクト グラフを読み取り、個々の XAML ノードが処理され、XamlXmlWriter がシリアル化された結果を XAML テキスト ファイルとして出力します。 ここで重要なのは、パスとシナリオはどちらも一度に 1 つの XAML ノードしか使用しない点と、XAML ノードは、XAML 型システムおよび .NET Framework XAML サービス API で定義されている標準的な方法で処理される点です。

フレームとスコープ

XAML ノード ループは、XAML ノード ストリーム内を線形に走査します。 ノード ストリームは、オブジェクト、他のオブジェクトを含むメンバーなどを走査します。 フレームとスタックの概念を実装することにより、XAML ノード ストリーム内でスコープを追跡することも便利です。 これは特に、ノード ストリーム内にいるときに、ノード ストリームをアクティブに調整する場合に言えることです。 ノード ループ ロジックの一環として実装されるフレームとスタックのサポートは、構造を DOM の観点からとらえた場合は、XAML ノード構造内を降下する中で、StartObject (または GetObject) および EndObject スコープをカウントできます。

オブジェクト ノードの走査および入力

ノード ストリームの最初のノードは XAML リーダーによって開かれたときに、ルート オブジェクトの開始オブジェクト ノードになります。 定義上、このオブジェクトは常に単一のオブジェクト ノードであり、ピアは存在しません。 実際の XAML の例では、ルート オブジェクトは追加のオブジェクトを保持する 1 つ以上のプロパティが設定されたものとして定義されます。このようなプロパティには、メンバー ノードが設定されます。 このメンバー ノードは 1 つ以上のオブジェクト ノードが設定されるか、最終的に値ノードになる場合もあります。 通常、ルート オブジェクトは XAML 名前スコープを定義します。これは構文上、XAML テキスト マークアップの属性として割り当てられますが、XAML ノード ストリーム表現の Namescope ノード型にマップされます。

次の XAML の例について考えます (これは任意に設定した XAML であり、.NET Framework の既存の型に基づいたものではありません)。 このオブジェクト モデルでは、FavorCollection は Favor の List<T> に該当すること、Balloon と NoiseMaker は Favor に割り当てることができること、Balloon.Color プロパティは WPF で既知の色名として色を定義する方法と同様に Color オブジェクトに基づくこと、Color は属性構文の型コンバーターをサポートしていることが想定されます。

XAML マークアップ

結果の XAML ノード ストリーム

<Party

Party の Namespace ノード

xmlns="PartyXamlNamespace">

Party の StartObject ノード

  <Party.Favors>

Party.Favors の StartMember ノード

暗黙の FavorCollection の StartObject ノード

暗黙の FavorCollection 項目プロパティの StartMember ノード

    <Balloon

Balloon の StartObject ノード

      Color="Red"

Color の StartMember ノード

  属性値文字列 "Red" の Value ノード

Color の EndMember

      HasHelium="True"

HasHelium の StartMember ノード

  属性値文字列 "True" の Value ノード

HasHelium の EndMember

    >

Balloon の EndObject

    <NoiseMaker>Loudest</NoiseMaker>

NoiseMaker の StartObject ノード

_Initialization の   StartMember ノード

    初期値文字列 "Loudest" の Value ノード

_Initialization の   EndMember ノード

NoiseMaker の EndObject

暗黙の FavorCollection 項目プロパティの EndMember ノード

暗黙の FavorCollection の EndObject ノード

  </Party.Favors>

Favors の EndMember

</Party>

Party の EndObject

XAML ノード ストリームでは、次の動作を想定できます。

  • Namespace ノードが存在する場合、xmlns で XAML 名前空間を宣言した StartObject の直前のストリームに追加されます。 XAML とノード ストリームの例を含む前の表をもう一度参照してください。 StartObject ノードと Namespace ノードがテキスト マークアップの宣言位置に入れ替えられる要領に注意してください。 これは典型的な動作であり、名前空間ノードはノード ストリームで適用するノードの前に常に表示されます。 この設計の目的は、名前空間情報はオブジェクト ライターに必須であり、オブジェクト ライターが型のマッピングを試みたり、オブジェクトを処理したりする前に認識される必要があることに基づいています。 ストリームのアプリケーション スコープの前に XAML 名前空間情報を配置すると、ノード ストリームを常にその配置の順序で処理しやすくなります。

  • 前述の注意事項により、ルートの StartObject ではなく、最初からノードを走査する場合、実際のほとんどのマークアップのケースで 1 つ以上の Namespace ノードを最初に読み取ることになります。

  • StartObject ノードの後には StartMember、Value、または直後に EndObject を配置できます。 直後に別の StartObject は配置できません。

  • StartMember の後には StartObject、Value、または直後に EndMember を配置できます。 この後に GetObject を配置できます (新しい値をインスタンス化する StartObject ではなく、親オブジェクトの既存の値から値が取得されると想定されるメンバーの場合)。 さらに、この後に Namespace ノードを配置できます。これは後の StartObject に適用されます。 直後に別の StartMember は配置できません。

  • Value ノードは値自体を表し、"EndValue" はありません。 この後に続けて配置できるのは、EndMember のみです。

    • 構築で使用される可能性があるオブジェクトの XAML 初期化テキストでは、オブジェクトと値の構造体は得られません。 代わりに、_Initialization という名前のメンバー専用のメンバー ノードが作成されます。 また、このメンバー ノードには、初期値文字列が含まれています。 存在する場合、_Initialization は常に最初の StartMember です。 _Initialization は、_Initialization がバッキング型で定義されたプロパティでないことを明示するため、XAML 言語の XAML 名前スコープによる一部の XAML サービス表現で修飾される場合があります。

    • メンバーと値の組み合わせで、値の属性設定を表します。 結果として、この値の処理に値コンバーターが関与する場合があります。値はプレーンな文字列です。 ただし、その処理結果は、このノード ストリームが XAML オブジェクト ライターで処理されるまで評価されません。 XAML オブジェクト ライターは、必要な XAML スキーマ コンテキスト、型システム マッピング、および値変換に必要なその他のサポートを保持しています。

  • EndMember ノードの後には、後続のメンバーの StartMember ノードまたはそのメンバー所有者の EndObject ノードを配置できます。

  • EndObject ノードの後には、EndMember ノードを配置できます。 また、コレクションの項目でオブジェクトがピアに該当するケースでは、StartObject ノードも配置できます。 または、この後に Namespace ノードを配置できます。これは後の StartObject に適用されます。

    • ノード ストリームを閉じるだけのケースでは、ルートの EndObject の後には何も配置できません。リーダーでこれ以上処理するファイルがなくなり、Read が false を返します。

値コンバーターと XAML ノード ストリーム

値コンバーターはマークアップ拡張機能の一般用語であり、型コンバーター (値シリアライザーを含む)、または XAML 型システムで値コンバーターとして報告されるその他の専用クラスを示します。 XAML ノード ストリームでは、型コンバーターの使用方法とマークアップ拡張機能の使用方法ではまったく異なる表現が使用されます。

XAML ノード ストリームの型コンバーター

型コンバーターの使用につながる属性セットは、XAML ノード ストリームではメンバーの値として報告されます。 XAML ノード ストリームでは、型コンバーターのインスタンス オブジェクトが生成されて、そのインスタンス オブジェクトに値が渡されることはありません。 型コンバーターの変換実装を使用するには、XAML スキーマ コンテキストを呼び出し、それを型のマッピングに使用する必要があります。 値の処理に使用する型コンバーター クラスを決定する場合でも、XAML スキーマ コンテキストが間接的に必要になります。 既定の XAML スキーマ コンテキストを使用する場合、その情報は XAML 型システムから使用できます。 XAML ライターに接続する前の段階で XAML ノード ストリーム レベルの型コンバーター クラス情報が必要な場合、設定対象のメンバーの XamlMember 情報から取得できます。 ただしそれ以外の場合は、型マッピング システムと XAML スキーマ コンテキストを必要とする残りの操作 (XAML オブジェクト ライターによるオブジェクトの作成など) が実行されるまでの間、型コンバーターの入力を XAML ノード ストリームでプレーンな値として保持する必要があります。

たとえば、次のクラス定義のアウトラインとその XAML の使用方法について考えます。

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"/>

この使用方法では XAML ノード ストリームのテキスト表現は、次のように表すことができます。

GameBoard を表す XamlType の StartObject

BoardSize を表す XamlMember の StartMember

テキスト文字列 "8x8" の Value ノード

BoardSize と一致する EndMember

GameBoard と一致する EndObject

このノード ストリームには型コンバーター インスタンスが存在しないことに注意してください。 ただし、BoardSize の XamlMemberXamlMember.TypeConverter を呼び出すことで、型コンバーター情報を取得できます。 有効な XAML スキーマ コンテキストを使用している場合は、ConverterInstance からインスタンスを取得することで、コンバーター メソッドを呼び出すこともできます。

XAML ノード ストリームのマークアップ拡張機能

マークアップ拡張機能の使用は、XAML ノード ストリームではメンバー内のオブジェクト ノードとして報告されます。この場合、オブジェクトはマークアップ拡張機能のインスタンスを表します。 したがって、マークアップ拡張機能の使用は、ノード ストリームの表現では型コンバーターの使用よりも明示的に表され、より細かい情報を提供します。 XamlMember 情報からはマークアップ拡張機能に関する情報は得られません。これは、この使用方法がマークアップのケースごとの状況に応じて変化することに起因します。型コンバーターのケースと異なり、型またはメンバーごとに固有または暗黙の情報は得られません。

オブジェクト ノードとしてのマークアップ拡張機能のノード ストリームの表現は、マークアップ拡張機能が XAML テキスト マークアップで属性形式で使用される場合 (一般的なケース) でも同じです。 明示的なオブジェクト要素形式を使用したマークアップ拡張機能の使用方法も同じ方法で処理されます。

マークアップ拡張機能のオブジェクト ノードには、そのマークアップ拡張機能のメンバーが存在する場合もあります。 位置指定パラメーターによる使用方法または明示的な名前付きパラメーターによる使用方法にかかわらず、XAML ノード ストリームの表現にはそのマークアップ拡張機能の使用方法が保持されています。

位置指定パラメーターによる使用方法では、XAML ノード ストリームには、その使用方法を記録した、XAML 言語で定義された _PositionalParameters プロパティが含まれています。 このプロパティは、Object 制約によるジェネリックな List<T> です。 この制約の対象は、文字列ではなくオブジェクトです。これは、位置指定パラメーターによる使用方法には、マークアップ拡張機能の使用方法がネストされている可能性があることに起因します。 使用方法の位置指定パラメーターにアクセスするには、リストを反復処理して、個々のリスト値のインデクサーを使用します。

名前付きパラメーターによる使用方法では、各名前付きパラメーターはノード ストリームでその名前のメンバー ノードとして表されます。 メンバー値は、必ずしも文字列ではありません。これは、マークアップ拡張機能の使用方法がネストされている可能性があることに起因します。

この段階では、マークアップ拡張機能から ProvideValue は呼び出されていません。 ただし、XAML リーダーおよび XAML ライターを接続した場合に呼び出されます。これにより、ノード ストリームで調べた時点で WriteEndObject がマークアップ拡張機能のノードで呼び出されます。 したがって、通常は、読み込みパスでオブジェクト グラフを形成する場合と同じ XAML スキーマ コンテキストを使用できる必要があります。 そうでない場合、想定されるサービスを使用できないので、この段階でマークアップ拡張機能の ProvideValue が例外をスローする可能性があります。

XAML ノード ストリームの XAML および XML 言語で定義されたメンバー

一部のメンバーは、明示的な XamlMember の検索または構築ではなく、XAML リーダーの解釈および規則に従って、XAML ノード ストリームに組み込まれます。 通常、これらのメンバーは XAML ディレクティブです。 場合によっては、ディレクティブを XAML ノード ストリームに組み込む XAML を読み取る操作になります。 つまり、元の入力 XAML テキストではメンバー ディレクティブを明示的に指定していませんが、構造上の XAML の規則に準拠し、XAML ノード ストリームで情報が失われる前に報告するために、XAML リーダーがディレクティブを挿入します。

次の一覧に、XAML リーダーによってディレクティブの XAML メンバー ノードが組み込まれるすべてのケースと、そのメンバー ノードが .NET Framework XAML サービスの実装でどのように識別されるかを示します。

  • オブジェクト ノードの初期化テキスト: このメンバー ノードの名前は _Initialization で、XAML ディレクティブを表し、XAML 言語の XAML 名前空間で定義されます。 その静的なエンティティは、Initialization から取得できます。

  • マークアップ拡張機能の位置指定パラメーター: このメンバー ノードの名前は _PositionalParameters であり、XAML 言語の XAML 名前空間で定義されます。 オブジェクトのジェネリック リストが常に含まれており、それぞれが、入力 XAML で指定された区切り記号文字 "," による分割で事前に区切られた位置指定パラメーターに相当します。 位置指定パラメーターのディレクティブの静的なエンティティは、PositionalParameters から取得できます。

  • 不明なコンテンツ: このメンバー ノードの名前は _UnknownContent です。 厳密な表現では、XamlDirective であり、XAML 言語の XAML 名前空間で定義されます。 このディレクティブは、XAML オブジェクト要素にソース XAML のコンテンツが含まれているものの、現在使用できる XAML スキーマ コンテキストに基づいてコンテンツ プロパティを判別できない場合に、センティネルとして使用されます。 XAML ノード ストリームで、このケースを検出するには、_UnknownContent という名前のメンバーをチェックします。 読み込みパスの XAML ノード ストリームで他のアクションが実行されない場合、任意のオブジェクトで _UnknownContent メンバーが検出されたときに、試行された WriteEndObject に対して既定の XamlObjectWriter がスローされます。 既定の XamlXmlWriter はスローされず、メンバーは暗黙のメンバーとして処理されます。 _UnknownContent の静的なエンティティは、UnknownContent から取得できます。

  • コレクションのコレクション プロパティ: XAML に使用されるコレクション クラスのバッキング CLR 型には、通常、コレクション項目を保持する専用の名前付きプロパティがありますが、バッキング型の解決前に XAML 型システムがそのプロパティを認識することはありません。 代わりに、XAML ノード ストリームによって Items プレースホルダーがコレクションの XAML 型のメンバーとして組み込まれます。 .NET Framework XAML サービス実装では、ノード ストリーム内のこのディレクティブまたはメンバーの名前は _Items です。 このディレクティブの定数は Items から取得できます。

    XAML ノード ストリームには、バッキング型の解決と XAML スキーマ コンテキストを基に解析できない項目が設定された Items プロパティが含まれることがあります。 次に例を示します。

  • XML で定義されたメンバー: XML で定義された xml:base、xml:lang、および xml:space の各メンバーは、.NET Framework XAML サービスの実装で、base、lang、および space という名前の XAML ディレクティブとして報告されます。 それぞれの名前空間は、XML 名前空間 http://www.w3.org/XML/1998/namespace です。 それぞれの定数は、XamlLanguage から取得できます。

ノードの順序

XamlXmlReader は、マークアップで表示した場合または XML として処理した場合に表示されるノードの順序に対して、XAML ノード ストリーム内の XAML ノードの順序を変更することがあります。 その目的は、XamlObjectWriter がノード ストリームを順方向でのみ処理できるように、ノードの順序を変更することです。 .NET Framework XAML サービスでは、ノードの並べ替えを XAML ライターに任せることなく、XAML リーダーが行います。これは、ノード ストリームの XAML オブジェクト ライター コンシューマー向けにパフォーマンスを最適化する処理です。

一部のディレクティブは、オブジェクト要素からオブジェクトを作成するための詳細を提供する目的で使用されます。 具体的には、Initialization、PositionalParameters、TypeArguments、FactoryMethod、Arguments の各ディレクティブです。 .NET Framework XAML サービスの XAML リーダーは、オブジェクトの StartObject に続く、ノード ストリーム内の最初のメンバーとしてこれらのディレクティブを配置しようとします。その理由については、次のセクションで説明します。

XamlObjectWriter の動作とノードの順序

XamlObjectWriter に対する StartObject は、オブジェクト インスタンスを直ちに構築するために XAML オブジェクト ライターに送信されるシグナルであるとは限りません。 XAML の一部の言語機能を使用すると、追加の入力でオブジェクトを初期化できるほか、初期オブジェクトを生成するために既定のコンストラクターの呼び出しに完全に依存することなく、プロパティを設定するだけで済みます。 こうした機能には、XamlDeferLoadAttribute、初期化テキスト、x:TypeArguments、マークアップ拡張機能の位置指定パラメーター、ファクトリ メソッドおよび関連付けられた x:Arguments ノード (XAML 2009) があります。 これらの各ケースでは、実際のオブジェクトの構築が遅延されます。ノード ストリームが並べ替えられるため、XAML オブジェクト ライターは、そのオブジェクトの種類に対する構築ディレクティブではない開始メンバーが検出された場合は、実際のインスタンス構築動作に依存して動作できます。

GetObject

GetObject が表す XAML ノードでは、XAML オブジェクト ライターは新しいオブジェクトを構築する代わりに、オブジェクトの格納プロパティの値を取得する必要があります。 XAML ノード ストリームで GetObject ノードが検出される代表例には、格納プロパティがバッキング型のオブジェクト モデルで意図的に読み取り専用になっている場合のコレクション オブジェクトやディクショナリ オブジェクトがあります。 このシナリオでは、通常、コレクションまたはディクショナリは所有する型の初期化ロジックによって作成および初期化されます (通常は空)。

参照

参照

XamlObjectReader

その他の技術情報

XAML サービス

.NET Framework XAML サービス用の XAML 名前空間