更新 : 2007 年 11 月
Windows Presentation Foundation (WPF) Designer for Visual Studio フレームワークは、デザイン時のメタデータを実装から切り離します。メタデータを実行時コードから切り離すことは、重要なデザイン上の原則です。その理由は、次のとおりです。
チーム間で物流の往復と統合が繰り返されると、メタデータをフレームワーク コードにコンパイルする作業の効率が低下します。
メタデータをコンパイルして実行時コードに含めると、WPF デザイナ や Expression Blend などの外部ツールを使用して後でメタデータを変更することができなくなります。これはアジリティ (敏捷性) に影響する大きな問題です。デザイン時メタデータがコードから分離されていない場合、Visual Studio がデザイナのバージョン管理を行うには .NET Framework の新しいバージョンが必要になります。
メタデータをコンパイルしてランタイムに含めると、ランタイム アセンブリのサイズが著しく増えます。また、デザイン時属性はランタイムの動作を遅くします。メモリに読み込まれる属性が増えることにより、リフレクションを使用するデータ バインディングなどのランタイム機能が影響を受けます。
デザイン時メタデータは、デザイナの "個性" を提供します。デザイナの機能は、主として、ランタイムではなく、デザイナをホストするアプリケーションに結び付けられています。WPF デザイナ および Expression Blend では、異なるメタデータを使用して、特定の種類のユーザーを対象とする機能セットが提供されます。
メタデータ ストア
メタデータ ストアは、デザイン時メタデータを格納する場所です。メタデータ ストアの API は簡単です。AddAttributeTable メソッドを呼び出して、メタデータ属性のテーブルを追加します。テーブルをメタデータ ストアに追加すると、そのテーブルで定義されている属性が 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 アセンブリが読み込まれる前に読み込まれます。デザイナ固有メタデータは、共有メタデータよりも優先されます。 |
メタデータ アセンブリの検索順序
プロジェクトから直接参照される参照は、次の順序で検索されます。
同じフォルダを参照先ランタイム アセンブリとして検索します。この場所は、ビルドがアセンブリを見つけるために使用するのと同じアルゴリズムによって検出されます。SDK のフォルダや追加のパスの検索もこれに含まれます。
コントロールのランタイム アセンブリがあるフォルダの "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