クラス、コンポーネント、コントロール
このトピックでは、コンポーネントとコントロールについて定義します。このトピックの説明は、コンポーネントまたはコントロールであるクラスをいつ実装するかを決定するのに役立ちます。
[!メモ]
このトピックでは、Windows フォームと ASP.NET クラスについて説明します。この説明は WPF クラスには当てはまりません。WPF コントロールの作成の詳細については、「コントロールの作成の概要」を参照してください。
実装のためのガイドラインを次に示します。
クラスで外部リソースを使用するが、そのクラスをデザイン サーフェイスでは使用しない場合は、System.IDisposable を実装するか、IDisposable を直接または間接的に実装するクラスから派生させます。
クラスをデザイン サーフェイス (Windows フォーム デザイナー、Web フォーム デザイナーなど) で使用する場合は、System.ComponentModel.IComponent を実装するか、IComponent を直接または間接的に実装するクラスから派生させます。IComponent は IDisposable の拡張であるために、IComponent 型は常に IDisposable 型です。IComponent ではない IDisposable 型に比べると、IComponent 型にはわずかなパフォーマンス オーバーヘッドがありますが、このオーバーヘッドは、デザイン時および実行時に IComponent を配置できる機能によって相殺されます。配置については、このトピックで後で説明します。
デザイン可能で (デザイン サーフェイスで使用される)、参照渡しでマーシャリングされるクラスを使用する場合は、System.ComponentModel.Component から派生させることができます。Component は、参照渡しでマーシャリングされる IComponent 型の基本実装です。
値渡しでマーシャリングされるデザイン可能なクラスを使用する場合は、System.ComponentModel.MarshalByValueComponent から派生させることができます。MarshalByValueComponent は、値渡しでマーシャリングされる IComponent 型の基本実装です。
オブジェクト モデル階層に IComponent 型を導入する必要がある場合に、単一継承のために Component や MarshalByValueComponent などの基本実装から派生させることができないときは IComponent を実装します。
ユーザー インターフェイスを提供するデザイン可能なクラスを使用する場合、そのクラスはコントロールです。コントロールは、基本コントロール クラスである System.Windows.Forms.Control または System.Web.UI.Control のどちらかから直接または間接的に派生させる必要があります。
[!メモ]
クラスがデザイン可能ではなく、外部リソースを保持していない場合は、IComponent 型や IDisposable 型は不要です。
コンポーネント、コントロール、コンテナー、および配置の定義について次に説明します。
コンポーネント
.NET Framework では、コンポーネントとは System.ComponentModel.IComponent インターフェイスを実装するクラスまたは IComponent を実装するクラスから直接または間接的に派生したクラスを意味します。プログラミングでは、コンポーネントという用語は、一般的に、再利用可能で、ほかのオブジェクトと対話できるオブジェクトに対して使われます。.NET Framework コンポーネントは、上に述べた一般的な要件を満たすだけでなく、外部リソースの制御やデザイン時サポートなどの機能を備えています。
外部リソースの制御
IComponent インターフェイスは IDisposable インターフェイスを拡張したもので、コントラクトに Dispose というメソッドを備えています。Dispose メソッドの実装では、コンポーネントは外部リソースを明示的に解放する必要があります。外部リソースを明示的に解放することにより、ガベージ コレクションが行う一貫性のない既定のクリーンアップではなく、リソースを解放するための一貫性のある方法を実現できます。開発者は、子コンポーネントでもリソースが解放されるようにするために、コンテインメント階層全体のDisposeを反映させる必要があります。また、派生されたコンポーネントでは、その基本クラスの Dispose メソッドを呼び出す必要があります。
[!メモ]
Dispose でリソースを明示的に制御する場合でも、コンポーネントの Dispose の呼び出しに失敗するとリソースがリークし続けるため、必ずファイナライザー (デストラクター) で暗黙のクリーンアップを行う必要があります。
Dispose を基本コンポーネントおよび派生コンポーネントに実装する場合のパターンを次の例に示します。
public class BaseComponent : IComponent {
// IComponent extends IDisposable.
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (disposing) {
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
}
// Simply call Dispose(false).
~BaseComponent(){
Dispose (false);
}
}
// Derived component.
public class DerivedComponent : BaseComponent {
protected override void Dispose(bool disposing) {
if (disposing) {
// Free other state.
}
// You must invoke the Dispose method of the base class.
base.Dispose(disposing);
// Free your own state.
...
}
// No finalizer/destructor.
// No Dispose() method.
}
' Design pattern for a base class.
Public Class BaseComponent
Implements IComponent
' Implement IDisposable
Public Overloads Sub Dispose()
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overloads Overridable Sub Dispose(disposing As Boolean)
If disposing Then
' Free other state (managed objects).
End If
' Free your own state (unmanaged objects).
' Set large fields to null.
End Sub
Protected Overrides Sub Finalize()
' Simply call Dispose(False).
Dispose (False)
End Sub
End Class
' Design pattern for a derived component.
Public Class DerivedComponent
Inherits BaseComponent
Protected Overloads Overrides Sub Dispose(disposing As Boolean)
If disposing Then
' Release managed resources.
End If
' Release unmanaged resources.
' Set large fields to null.
' Call Dispose on your base class.
Mybase.Dispose(disposing)
End Sub
' The derived class does not have a Finalize method
' or a Dispose method with parameters because it inherits
' them from the base class.
End Class
デザイン時サポート
.NET Framework のコンポーネントの重要な機能の 1 つは、コンポーネントがデザイン可能であることです。つまり、コンポーネントであるクラスを、Visual Studio などの RAD (Rapid Application Development) 環境で使用できます。コンポーネントを Visual Studio のツールボックスに追加し、フォーム上にドラッグ アンド ドロップして、デザイン サーフェイスで操作できます。IComponent 型のデザイン時サポートは .NET Framework に組み込まれているため、コンポーネント開発者は追加の作業を行わずに基本のデザイン時機能を利用できます。
デザイン時サポートの詳細については、「コンポーネントのデザイン時属性」および「デザイン時サポートの拡張」を参照してください。
コンポーネントのホスト
コンポーネントは、コンテナー (このトピックで後に定義します) 内に配置 (格納) できます。配置されたコンポーネントは、サイト (このトピックで後に定義します) を通じてコンテナーとやりとりします。また、サイトを通じてコンテナーに対してサービスを照会したり、コンテナーからサービスを取得したりできます。コンテナーが破棄されたときに、リソースが確実に解放されるようにするために、コンテナーは IDisposable インターフェイスを実装している必要があります。Dispose メソッドの実装では、コンテナーは保持しているすべてのリソースを解放し、各コンテナコンポーネントの Dispose メソッドを呼び出す必要があります。
コンテインメントは論理的であり、ビジュアルに表現される必要はありません。データベース コンポーネントが配置される中間層コンテナーは、ビジュアルでないコンテインメントの例です。ビジュアル コンテインメントは、Visual Studio の Windows フォーム デザイナーおよび Web フォーム デザイナーで表示できます。ビジュアル デザイン サーフェイスは、フォーム コンポーネント (Web フォームでは、ページ コンポーネント) をホストするコンテナーです。
コンポーネントのマーシャリング
コンポーネントは、リモート処理可能にしたり、リモート処理不可能にすることができます。リモート処理可能コンポーネントは、参照渡しまたは値渡しでマーシャリングされます。マーシャリングには、アプリケーション ドメイン (軽量プロセス)、プロセス、コンピューターなどの境界を越えてオブジェクトを送信することが含まれます。オブジェクトが参照渡しでマーシャリングされる場合は、オブジェクトに対してリモート呼び出しを行うプロキシが作成されます。オブジェクトが値渡しでマーシャリングされる場合は、オブジェクトのシリアル化されたコピーが、関連する境界を越えて送信されます。
システム リソースをカプセル化したリモート処理可能コンポーネントのサイズが大きいか、またはコンポーネントが単独のインスタンスとして存在する場合には、参照渡しでマーシャリングする必要があります。参照渡しでマーシャリングされるコンポーネントの基本クラスは、System.ComponentModel.Component です。この基本クラスは IComponent を実装しており、MarshalByRefObject から派生されます。.NET Framework クラス ライブラリの多くのコンポーネントは、System.Windows.Forms.Control (Windows フォーム コントロールの基本クラス)、System.Web.Services.WebService (ASP.NET を使用して作成される XML Web サービスの基本クラス)、および System.Timers.Timer (反復するイベントを生成するクラス) を含む Component から派生します。
状態を単純に保持するリモート処理可能コンポーネントは、値渡しでマーシャリングする必要があります。値渡しでマーシャリングされるコンポーネントの基本クラスは、System.ComponentModel.MarshalByValueComponent です。この基本クラスは IComponent を実装しており、Object から派生されます。.NET Framework クラス ライブラリの中で、MarshalByValueComponent から派生されるコンポーネントはごく少数です。そのようなコンポーネントは、すべて System.Data 名前空間 (DataColumn、DataSet、DataTable、DataView、および DataViewManager) に含まれています。
[!メモ]
値渡しでマーシャリングされるオブジェクトの基本クラスは Object で、参照渡しでマーシャリングされるオブジェクトの基本クラスは MarshalByRefObject ですが、それに対応する派生クラスは、それぞれ MarshalByValueComponent と Component です。名前付け方法の基本的な考え方として、より一般的に使用される型ほど、より単純な名前が付けられます。
コンポーネントをリモート処理不可能にする場合は、Component の基本実装から派生させず、IComponent を直接実装してください。
Control
コントロールは、ユーザー インターフェイス (UI) 機能を提供する (または有効化する) コンポーネントです。.NET Framework には、コントロールの基本クラスが 2 種類用意されています。その 1 つはクライアント側 Windows フォーム コントロールの基本クラスで、もう 1 つは ASP.NET サーバー コントロールの基本クラスです。それらは、System.Windows.Forms.Control および System.Web.UI.Control です。.NET Framework クラス ライブラリのすべてのコントロールは、これら 2 つのクラスから直接または間接的に派生されています。 System.Windows.Forms.Control は Component から派生され、それ自体に UI 機能を備えています。System.Web.UI.Control は IComponent を実装し、そのインフラストラクチャによって UI 機能を簡単に追加できるようになります。
[!メモ]
すべてのコントロールはコンポーネントですが、すべてのコンポーネントはコントロールではありません。
コンテナーとサイト
Windows フォームまたは Web フォーム ページ (ASP.NET ページ) 用のコンポーネントやコントロールを作成する場合には、コンテナーやサイトを実装する必要はありません。Windows フォーム用および Web フォーム用のデザイナーは、Windows フォームおよび ASP.NET サーバー コントロールのコンテナーです。コンテナーは、その中に配置されているコンポーネントやコントロールに対してサービスを提供します。デザイン時には、コントロールはデザイナー内に配置され、デザイナーからサービスを受け取ります。コンテナーとサイトの定義を次に示します。
Container
コンテナーは、System.ComponentModel.IContainer インターフェイスを実装するクラス、またはこのインターフェイスを実装するクラスから派生したクラスです。コンテナーは、そのコンテナーの子コンポーネントと呼ばれる 1 つ以上のコンポーネントを論理的に包含します。Site
サイトは、System.ComponentModel.ISite インターフェイスを実装するクラス、またはこのインターフェイスを実装するクラスから派生したクラスです。サイトは、コンテナーの子コンポーネントを管理したり、子コンポーネントと通信したりするために、コンテナーによって提供されます。一般に、コンテナーとサイトは 1 単位として実装します。
参照
概念
その他の技術情報
.NET Framework を使用したカスタム Windows フォーム コントロールの開発