类、组件和控件

更新:2007 年 11 月

本主题对组件和控件进行了定义;此处进行的讨论可以帮助您决定何时实现一个是组件或控件的类。

以下列表为实施者提供了全面的指南。

下面是组件、控件、容器和站点的定义。

组件

在 .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 中,组件的一个重要功能就是它们是可设计的,这意味着作为组件的类可用于快速应用程序开发 (RAD) 环境(如 Visual Studio)中。可将组件添加到 Visual Studio 的工具箱中,也可将组件拖放到某个窗体上,还可以在设计图面上对组件进行操作。请注意,对 IComponent 类型的基本设计时支持已经内置于 .NET Framework 中;组件开发人员无须进行额外的工作就可利用基本设计时功能。

有关设计时支持的更多信息,请参见 组件的设计时属性 (Attribute)扩展设计时支持

承载组件

组件可以被放置(承载)在一个容器(本主题稍后部分进行了定义)中。当组件被放置后,它通过其站点(本主题稍后部分进行了定义)与容器进行交互并能够通过站点从其容器查询并得到服务。为了确保资源在容器被拆卸后释放,容器必须实现 IDisposable 接口。在其 Dispose 方法的实现中,容器必须释放它保留的所有资源,并调用它包含的每个组件的 Dispose 方法。

包容是逻辑上的,不需要可视的表示形式。放置数据库组件的中间层容器就是非可视包容的一个示例。可在 Visual Studio 的 Windows 窗体设计器和 Web 窗体设计器中找到可视包容。可视化设计图面是承载窗体组件(Web 窗体中的页组件)的容器。

封送组件

组件可以是可远程控制的或不可远程控制的。可远程控制的组件由引用或值进行封送。封送涉及跨边界(如应用程序域(轻量进程)、进程、甚至是计算机)发送对象。当对象由引用封送时,会创建一个代理对该对象进行远程调用。当对象由值进行封送时,跨相关边界发送该对象的一个序列化的副本。

以下可远程控制的组件应该由引用封送:封装系统资源的可远程控制组件,较大的可远程控制组件或作为单个实例存在的可远程控制组件。按引用封送的组件的基类是 System.ComponentModel.Component。该基类实现 IComponent 并从 MarshalByRefObject 派生。.NET Framework 类库中的许多组件从 Component 派生,包括 System.Windows.Forms.Control(Windows 窗体控件的基类)、System.Web.Services.WebService(使用 ASP.NET 创建的 XML Web 服务的基类)和 System.Timers.Timer(生成递归事件的类)。

仅保留状态的可远程控制组件应该由值封送。按值封送的组件的基类是 System.ComponentModel.MarshalByValueComponent。该基类实现 IComponent 并从 Object 派生。.NET Framework 类库中只有少量组件从 MarshalByValueComponent 派生。所有此类组件都在 System.Data 命名空间中(DataColumnDataSetDataTableDataViewDataViewManager)。

说明:

按值和按引用封送的对象的基类分别是 ObjectMarshalByRefObject,但对应的派生类名为 MarshalByValueComponentComponent。命名方案背后的逻辑是越常用的类型,其名称就越简单。

如果不对组件进行远程控制,则不要从 Component 的基实现派生,而应直接实现 IComponent

有关对象远程控制的更多信息,请参见 .NET 远程处理概述

控件

控件是提供(或实现)用户界面 (UI) 功能的组件。.NET Framework 为控件提供两个基类:一个用于客户端 Windows 窗体控件,另一个用于 ASP.NET 服务器控件。它们是 System.Windows.Forms.ControlSystem.Web.UI.Control。.NET Framework 类库中的所有控件直接或间接从这两个类派生。System.Windows.Forms.ControlComponent 派生,本身提供 UI 功能。System.Web.UI.Control 实现 IComponent 并提供可在其上轻松添加 UI 功能的基础结构。

说明:

每个控件都是一个组件,但并不是每个组件都是控件。

容器和站点

如果您正在为 Windows 窗体或 Web 窗体页(ASP.NET 页)开发组件和控件,则不需要实现容器或站点。Windows 窗体和 Web 窗体的设计器就是 Windows 窗体和 ASP.NET 服务器控件的容器。容器向放置在其中的组件和控件提供服务。在设计时,控件放置在设计器中并从设计器获得服务。为了保持完整性,以下给出了容器和站点的定义。

  • Container
    容器是一个实现 System.ComponentModel.IContainer 接口的类,或从实现该接口的类派生的类。容器在逻辑上包含一个或多个组件,这些组件叫做容器的子组件。

  • Site
    站点是一个实现 System.ComponentModel.ISite 接口的类,或从实现该接口的类派生的类。站点由容器提供,用来管理其子组件及与子组件进行通信。通常,容器和站点作为一个单元来实现。

请参见

概念

属性概述

组件的设计时属性 (Attribute)

其他资源

使用 .NET Framework 开发自定义 Windows 窗体控件

开发自定义 ASP.NET 服务器控件

扩展设计时支持