型記述子の概要
TypeDescriptor アーキテクチャは、.NET リフレクションの機能を拡張します。
型記述子のアーキテクチャ
TypeDescriptor アーキテクチャは、コア リフレクション エンジンに基づいて構築されており、ルールおよび機能が追加されています。たとえば、TypeDescriptor クラスは IContainer からの拡張プロパティのマージをサポートしており、IDesigner を介したプロパティおよびイベントのフィルター処理もサポートしています。
また、TypeDescriptor アーキテクチャにより、いくつかの機能が実現されています。次の表は、アーキテクチャの機能を示しています。
機能 |
Description |
---|---|
インスタンスの代替 |
ある型が要求されたときに、それとは別の任意の型を作成できます。 |
メタデータの代替 |
オブジェクトのメタデータを変更できます。 |
属性のリダイレクト |
属性を動的に指定できます。 |
ターゲットの代替およびシャドウ |
1 つのオブジェクトを別のオブジェクトの代わりに使用できます。 |
型記述子の拡張サポート |
他のオブジェクトによって追加されたオブジェクト プロパティにアクセスできます。 |
これらの機能をサポートするために、TypeDescriptor クラスが .NET Framework コンポーネント モデルのさまざまな機能と密接に統合されています。COM オブジェクト、拡張プロバイダー、デザイナー、および CLR プロパティと互換性があります。
[!メモ]
TypeDescriptor アーキテクチャは、ランタイム コードとデザイン時コードの両方で使用できます。
機能拡張をサポートするために、TypeDescriptor クラスには TypeDescriptionProvider と呼ばれるコンパニオン クラスと、TypeDescriptionProviderAttribute と呼ばれるコンパニオン属性が含まれています。クラスで TypeDescriptionProviderAttribute を使用すると、デザインの目的に合わせて、メタデータの異なる公開方法を導入できます。
TypeDescriptionProvider クラス
TypeDescriptionProvider クラスは、TypeDescriptor クラスのプラグインと見なすことができます。TypeDescriptor の 1 つのインスタンスに対して複数の型記述プロバイダー クラスが存在でき、それぞれが TypeDescriptor にメタデータを提供できます。
TypeDescriptionProvider 属性
TypeDescriptionProviderAttribute はクラス上に配置できる属性です。この属性は、型にカスタムの型記述プロバイダーが関連付けられていることを示すために使用されます。つまり、この属性により、メタデータを介して型記述プロバイダーをインストールできます。この型が TypeDescriptor クラス上のいずれかの API に渡されると、TypeDescriptor はこの属性を検出し、そこに記述されている型記述プロバイダーのインスタンスを作成し、プロバイダーを TypeDescriptor の内部テーブルにフックします。これが終わると、TypeDescriptor は API の処理を続行します。この処理により、型はカスタムの型記述プロバイダーを必要に応じて自動的にインストールできます。
型記述子の機能
TypeDescriptor アーキテクチャは、.NET Framework リフレクションによって提供される機能を拡張します。
インスタンスの代替
インスタンスの代替は、ある型を作成する必要があるときに、実際に作成された型が要求したものと異なる場合に発生します。インスタンスの代替は、new のすべての呼び出しを CreateInstance メソッドの呼び出しに置換することで実行されます。このメソッドは、TypeDescriptor 内の内部テーブルで、指定したデータ型に関連付けられている TypeDescriptionProvider オブジェクトを検索します。見つかったら、そのオブジェクトに呼び出しを代行させます。
メタデータの代替
メタデータの代替は、1 つ以上のオブジェクトで使用できるメタデータを変更する場合に発生します。メタデータの代替の一般的な用途は、デザイナーの実装内です。メタデータの代替は、TypeDescriptor で次のメソッドを使用して追加および削除できる型記述プロバイダーで実行します。
属性のリダイレクト
.NET Framework オブジェクト モデルで、プロパティの型が意図的に非固有になっていることがあります。たとえば、DataGridView クラスの DataSource プロパティは、object として入力されます。このデザインでは、データ ソースはさまざまな種類の入力を受け入れることができますが、メタデータを追加してプロパティの特性を表すための共通の場所はありません。.NET Framework 内の各データ ソースのプロパティでは、型コンバーターとユーザー インターフェイス (UI) 型エディターに対して同一のメタデータが必要です。
AttributeProviderAttribute クラスは、このような状況を解決します。この属性がプロパティに配置されると、プロパティ記述子の Attributes コレクションの属性を取得するためのルールが変更されます。通常、プロパティ記述子はローカル属性を収集し、それらをプロパティ型からの属性にマージします。AttributeProviderAttribute 属性が適用されると、実際のプロパティ型ではなく、AttributeProviderAttribute から返された型から属性を受け取ります。データ ソースの特定の型として IListSource を指すために AttributeProviderAttribute がデータ ソースで使用され、適切なメタデータが IListSource に配置されて、データ バインディングが有効になります。このリダイレクトにより、Visual Studio などの外部パーティは簡単にすべてのデータ ソースにメタデータを追加できるようになります。
AttributeProviderAttribute で宣言した型から取得された属性の優先順位は、プロパティの型の属性とプロパティの属性の間です。使用可能な属性の完全なセットは、これらを合わせたもので、次の一覧に優先順位の順に示します。
プロパティ属性
属性プロバイダー属性
プロパティ型属性
ターゲットの代替およびシャドウ
ターゲットの代替は、オブジェクトが他のオブジェクトを表す場合に発生します。ターゲットの代替の一般的な用途は、デザイナーの実装内です。
.NET Framework Designer のアーキテクチャでは、コンポーネントにデザイナーを関連付けることができます。このデザイナーは、IDesignerFilter を実装して、独自のプロパティを提供できます。これらのプロパティは、デザイナーが関連付けられているコンポーネントのプロパティ セットにマージされます。これらのプロパティは、それまでコンポーネントに存在しなかったものでもかまいません。また、コンポーネントで既に定義されているプロパティと同じ名前および型にすることもできます。新しいプロパティが既存のプロパティと名前および型が同じ場合、それをシャドウと呼びます。デザイナーがコンポーネントの既存のプロパティを非表示 (シャドウ) にするためです。プロパティのシャドウを次の図に示します。
ここでは、コンポーネントは 2 つのプロパティを提供し、デザイナーも 2 つのプロパティを提供しています。Text プロパティはデザイナーとコンポーネントの両方で提供され、シャドウされています。GetProperties の呼び出しの最終的な結果は 3 つのプロパティです。1 つはコンポーネントに、2 つはデザイナーに存在します。
このプロパティのフィルター処理は、デザイン サーフェイスが実装する ITypeDescriptorFilterService を使用することによって実現されます。TypeDescriptor の機能は、プロパティで値を設定するときに必要です。Grid プロパティで値を設定するコードは、次のようになります。
gridProp.SetValue(component, value);
プロパティに関する実際の型情報は、コンポーネントではなく、デザイナーのインスタンスをポイントします。実際にプロパティを設定するためにリフレクションが呼び出された場合、コンポーネントのインスタンスはデザイナーの型と一致しないため、呼び出しによってターゲット呼び出しの例外が発生します。
TypeDescriptor クラスには、このような問題を解決するための固有のロジックがあります。プロパティが呼び出された場合、TypeDescriptor クラスはメンバー型が渡されたオブジェクトのインスタンスであるかどうかを確認します。その場合は、呼び出しを続行します。そうでない場合、クラスはオブジェクトのデザイナーを探そうとします。デザイナーが見つかり、それが正しい型だった場合、クラスはコンポーネントのインスタンスをデザイナーのインスタンスに置換します。
TypeDescriptor の次のメソッドは、ターゲットの代替をサポートしています。
拡張された型記述子のサポート
GetExtendedTypeDescriptor メソッドは、指定されたオブジェクトについて、拡張されたカスタム型記述子を返します。拡張された型記述子はカスタム型記述子です。他のオブジェクトがこのオブジェクトに追加していて、実際にはオブジェクトで定義されていないプロパティを提供します。たとえば、.NET Framework コンポーネント モデルでは、IExtenderProvider インターフェイスを実装するオブジェクトは、同じ IContainer 内に存在する他のオブジェクトにプロパティをアタッチできます。GetTypeDescriptor メソッドは、これらの追加の拡張プロパティを提供する型記述子を返しません。ただし、GetExtendedTypeDescriptor は、これらの拡張プロパティのセットを返します。TypeDescriptor クラスは、これら 2 つのプロパティ コレクションを自動的にマージします。
[!メモ]
.NET Framework コンポーネント モデルは拡張プロパティのみをサポートしていますが、型記述プロバイダーがサポートしている場合は GetExtendedTypeDescriptor を拡張属性およびイベントに使用できます。
参照
関連項目
TypeDescriptionProviderAttribute