メタデータ ストア

[このドキュメントはプレビュー版であり、後のリリースで変更されることがあります。 空白のトピックは、プレースホルダーとして挿入されています。]

WPF Designer for Visual Studio フレームワークは、デザイン時のメタデータを実装から切り離します。 メタデータを実行時コードから切り離すことは、重要なデザイン上の原則です。その理由は、次のとおりです。

  • チーム間で物流の往復と統合が繰り返されると、メタデータをフレームワーク コードにコンパイルする作業の効率が低下します。

  • メタデータをコンパイルして実行時コードに含めると、WPF デザイナー や Expression Blend などの外部ツールを使用して後でメタデータを変更することができなくなります。 これはアジリティ (敏捷性) に影響する大きな問題です。デザイン時メタデータがコードから分離されていない場合、Visual Studio がデザイナーのバージョン管理を行うには .NET Framework の新しいバージョンが必要になります。

  • メタデータをコンパイルしてランタイムに含めると、ランタイム アセンブリのサイズが著しく増えます。 また、デザイン時属性はランタイムの動作を遅くします。 メモリに読み込まれる属性が増えることにより、リフレクションを使用するデータ バインディングなどのランタイム機能が影響を受けます。

  • デザイン時メタデータは、デザイナーの "個性" を提供します。 デザイナーの機能は、主として、ランタイムではなく、デザイナーをホストするアプリケーションに結び付けられています。 WPF デザイナー および Expression Blend では、異なるメタデータを使用して、特定の種類のユーザーを対象とする機能セットが提供されます。

メタデータ ストア

メタデータ ストアは、デザイン時メタデータを格納する場所です。 メタデータ ストアの API は簡単です。 AddAttributeTable(AttributeTable) メソッドを呼び出して、メタデータ属性のテーブルを追加します。 テーブルをメタデータ ストアに追加すると、そのテーブルで定義されている属性が TypeDescriptor クエリで使用できるようになります。 型が既にクエリ済みで、その型の追加の属性がテーブルに含まれる場合は、Refreshed イベントが発生して、型のメタデータが変更されたことが通知されます。

属性テーブル

属性テーブルは、本質的には読み取り専用ディクショナリですが、キーと値は別々に計算されます。 特定の型の属性があるかどうかを属性テーブルに問い合わせると効率的です。 実際の属性セットが要求に応じて作成されます。 GetCustomAttributes メソッドを呼び出して、特定の型のカスタム メタデータを取得します。

属性テーブルは、型のプロパティのみをサポートしています。 属性テーブルは、フィールドまたはメソッドの属性はサポートしていません。

属性テーブル ビルダー

属性テーブルを作成するには、まず AttributeTableBuilder クラスのインスタンスを作成します。 AddCustomAttributes オーバーロードを呼び出すことにより、属性テーブル ビルダーにメタデータを追加します。 メタデータを追加し終わったら、CreateTable メソッドを呼び出すことにより、属性テーブル ビルダーから属性テーブルを生成します。 属性テーブル ビルダーのメソッドは、コールバック デリゲートをサポートするため、属性テーブルの作成は必要になるまで延期できます。

カスタム属性の作成

メタデータ ストアは、カスタム属性に TypeId プロパティの正しく定義されたオーバーライドがあることを前提としています。 メタデータ ストアでは、同じ型または異なる型の 2 つの属性を同じインスタンスとして扱うかどうかを判断するために TypeId プロパティが使用されます。

基本 Attribute クラスには TypeId プロパティが次のように定義されています。

    public class Attribute
    {
        ...

        public virtual object TypeId
        {
            get
            {
                return base.GetType();
            }
        }

        ...
    }

この実装では、同じ Attribute 型の 2 つのインスタンスが同じ属性として認識されるように作成されます。 インスタンスの 1 つは、既定の TypeDescriptor 実装によって無視されます。 FeatureAttribute クラスの場合のように、これがカスタム属性に期待される動作ではない場合、カスタム属性で TypeId プロパティをオーバーライドして、型インスタンスごとに固有のオブジェクトを返すようにします。 たとえば、FeatureAttribute クラスでは、次のコードを使用して TypeId プロパティをオーバーライドします。

public override object TypeId
{
    get { return this; }
}

this によってオブジェクト インスタンスごとに固有のオブジェクトが表されるため、FeatureAttribute は、安全に同じクラスを複数回修飾し、メタデータ ストアと同時に使用されるときに期待どおりの結果を提供することができます。

メタデータ アセンブリの名前付け規則

デザイン時コードは、特殊なメタデータ アセンブリで配布されます。 すべてのデザイナーによってサポートされるデザイン時機能は、メイン ライブラリの名前に ".Design" を付加した名前のアセンブリとして配置されます。 Visual Studio だけでサポートされるデザイン時機能は、メイン ライブラリの名前に ".VisualStudio.Design" を付加した名前のアセンブリとして配置されます。 CustomControlLibrary.dll という名前の実行時コントロール ライブラリに使用する名前の例を次の表に示します。

デザイナー

デザイン時アセンブリ名

Visual Studio のみ

CustomControlLibrary.VisualStudio.Design.dll

Expression Blend のみ

CustomControlLibrary.Expression.Design.dll

すべてのデザイナー

CustomControlLibrary.Design.dll

メタデータ アセンブリの読み込み

デザイナーにランタイム アセンブリが読み込まれると、対応するメタデータ アセンブリも検索されます。 対応するメタデータ アセブリが見つかると、ランタイム アセンブリが読み込まれた直後にそれも読み込まれます。

新しいアセンブリ参照をプロジェクトに追加すると、対応するすべてのメタデータ アセンブリが検索され、見つかった場合にそれが読み込まれます。

メタデータ アセンブリは、再ビルド時に再度読み込まれます。

注意

*.Design.dll メタデータ アセンブリは、デザイナー固有の *.VisualStudio.Design.dll アセンブリおよび *.Expression.Design.dll アセンブリが読み込まれる前に読み込まれます。デザイナー固有メタデータは、共有メタデータよりも優先されます。

メタデータ アセンブリの検索順序

プロジェクトから直接参照される参照は、次の順序で検索されます。

  1. 同じフォルダーを参照先ランタイム アセンブリとして検索します。 この場所は、ビルドがアセンブリを見つけるために使用するのと同じアルゴリズムによって検出されます。SDK のフォルダーや追加のパスの検索もこれに含まれます。

  2. コントロールのランタイム アセンブリがあるフォルダーの "Design" サブフォルダーを検索します。

コントロールのランタイム アセンブリはグローバル アセンブリ キャッシュ (GAC) から読み込むことができますが、参照は常に GAC の外部の場所を指します。 多くの場合、この場所は SDK フォルダーです。 WPF デザイナー では、プロジェクトの HintPath パスが指定されていないときでも、Visual Studio API を使用して、ファイル システム上の参照先アセンブリを検索します。 デザイナーは、コントロールのランタイム アセンブリが読み込まれる場所からではなく、コントロールのランタイム アセンブリが参照される場所からメタデータ アセンブリを読み込もうとします。

間接的に参照されるアセンブリは読み込まれます。これは、間接的に参照されるアセンブリはプロジェクトによって参照されるアセンブリから参照されるためです。 たとえば、プロジェクトにアセンブリ MyAssembly への参照があり、MyAssembly に MyOtherAssembly への参照があって MyOtherAssembly はプロジェクトから直接参照されていない場合、MyOtherAssembly は間接的に参照されていることになります。

このようなアセンブリはビルドで必須とされず、ビルド システムは間接的に参照されているアセンブリの場所をファイル システムで検索しません。 デザイナーが間接的に参照されるアセンブリを読み込む方法を次の表に示します。

参照されるアセンブリ

検索プロシージャ

GAC から読み込まれるファイル

対応するメタデータ アセンブリが SDK フォルダーで検索されます。 このアセンブリが見つかると、そのパスと "Design" サブフォルダーは、対応する任意のメタデータ アセンブリの検索に使用されます。

GAC の外部の場所から読み込まれるファイル

対応するメタデータ アセンブリがランタイム アセンブリのパスと "Design" サブフォルダーで検索されます。

IRegisterMetadata 実装の検索

メタデータ アセンブリには、IRegisterMetadata インターフェイスの 1 つ以上の実装が含まれている必要があります。 IRegisterMetadata 実装は、リフレクションを使用して検出されます。 アセンブリに複数の IRegisterMetadata 実装がある場合、各実装はリフレクション API から返された順序でインスタンス化され、呼び出されます。

参照

参照

Microsoft.Windows.Design.Metadata

MetadataStore

AttributeTable

AttributeTableBuilder

FeatureAttribute

その他の技術情報

WPF Designer の機能拡張