クラス、コンポーネント、コントロール

更新 : 2007 年 11 月

このトピックでは、コンポーネントとコントロールについて定義します。このトピックの説明は、コンポーネントまたはコントロールであるクラスをいつ実装するかを決定するのに役立ちます。

実装のためのガイドラインを次に示します。

  • クラスで外部リソースを使用するが、そのクラスをデザイン サーフェイスでは使用しない場合は、System.IDisposable を実装するか、IDisposable を直接または間接的に実装するクラスから派生させます。

  • クラスをデザイン サーフェイス (Windows フォーム デザイナ、Web フォーム デザイナなど) で使用する場合は、System.ComponentModel.IComponent を実装するか、IComponent を直接または間接的に実装するクラスから派生させます。IComponentIDisposable の拡張であるために、IComponent 型は常に IDisposable 型です。IComponent ではない IDisposable 型に比べると、IComponent 型にはわずかなパフォーマンス オーバーヘッドがありますが、このオーバーヘッドは、デザイン時および実行時に IComponent を配置できる機能によって相殺されます。配置については、このトピックで後で説明します。

  • デザイン可能な (デザイン サーフェイスで使用される)、参照渡しでマーシャリングされるクラスを使用する場合は、System.ComponentModel.Component から派生させることができます。Component は、参照渡しでマーシャリングされる IComponent 型の基本実装です。

  • 値渡しでマーシャリングされるデザイン可能なクラスを使用する場合は、System.ComponentModel.MarshalByValueComponent から派生させることができます。MarshalByValueComponent は、値渡しでマーシャリングされる IComponent 型の基本実装です。

  • オブジェクト モデル階層に IComponent 型を導入する必要がある場合に、単一継承のために ComponentMarshalByValueComponent などの基本実装から派生させることができないときは 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 などの Rapid Application Development (RAD) 環境で使用できます。コンポーネントを 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 名前空間 (DataColumnDataSetDataTableDataView、および DataViewManager) に含まれています。

メモ :

値渡しでマーシャリングされるオブジェクトの基本クラスは Object で、参照渡しでマーシャリングされるオブジェクトの基本クラスは MarshalByRefObject ですが、それに対応する派生クラスは、それぞれ MarshalByValueComponentComponent です。名前付け方法の基本的な考え方として、より一般的に使用される型ほど、より単純な名前が付けられます。

コンポーネントをリモート処理不可能にする場合は、Component の基本実装から派生させず、IComponent を直接実装してください。

オブジェクトのリモート処理の詳細については、「.NET リモート処理の概要」を参照してください。

コントロール

コントロールは、ユーザー インターフェイス (UI) 機能を提供する (または有効化する) コンポーネントです。.NET Framework には、コントロールの基本クラスが 2 種類、用意されています。その 1 つはクライアント側 Windows フォーム コントロールの基本クラスで、もう 1 つは ASP.NET サーバー コントロールの基本クラスです。それらは、System.Windows.Forms.Control および System.Web.UI.Control です。.NET Framework クラス ライブラリのすべてのコントロールは、これら 2 つのクラスから直接または間接に派生されています。System.Windows.Forms.ControlComponent から派生され、それ自身で UI 機能を備えています。System.Web.UI.ControlIComponent を実装しており、UI 機能を簡単に追加できるようにするインフラストラクチャを提供します。

メモ :

すべてのコントロールはコンポーネントですが、すべてのコンポーネントはコントロールではありません。

コンテナとサイト

Windows フォームまたは Web フォーム ページ (ASP.NET ページ) 用のコンポーネントやコントロールを作成する場合には、コンテナやサイトを実装する必要はありません。Windows フォーム用および Web フォーム用のデザイナは、Windows フォームおよび ASP.NET サーバー コントロールのコンテナです。コンテナは、その中に配置されているコンポーネントやコントロールに対してサービスを提供します。デザイン時には、コントロールはデザイナ内に配置され、デザイナからサービスを受け取ります。コンテナとサイトの定義を次に示します。

  • Container
    コンテナは、System.ComponentModel.IContainer インターフェイスを実装するクラス、またはこのインターフェイスを実装するクラスから派生したクラスです。コンテナは、そのコンテナの子コンポーネントと呼ばれる 1 つ以上のコンポーネントを論理的に包含します。

  • Site
    サイトは、System.ComponentModel.ISite インターフェイスを実装するクラス、またはこのインターフェイスを実装するクラスから派生したクラスです。サイトは、コンテナの子コンポーネントを管理したり、子コンポーネントと通信したりするために、コンテナによって提供されます。一般に、コンテナとサイトは 1 単位として実装します。

参照

概念

プロパティの概要

コンポーネントのデザイン時属性

その他の技術情報

.NET Framework を使用したカスタム Windows フォーム コントロールの開発

ASP.NET カスタム サーバー コントロールの開発

デザイン時サポートの拡張