Skip to main content
黑话筒

转载:类别、元件和控制项的比较

这个主题将定义元件和控制项;这里的讨论应可协助您决定何时应实作元件或控制项的类别。

下列清单为实作器提供了较松的方针。

接着说明的是元件、控制项、容器 (Container) 和网站的定义。

元件

在 .NET Framework,元件是指实作 System.ComponentModel.IComponent 介面的类别,或者从实作 IComponent 之类别直接或间接衍生的类别。在程式设计中,元件一词通常是使用於可以重复使用而且可以与其他物件互动的物件。.NET Framework 元件不仅满足这些一般性的要求,并且还额外地提供一些功能,例如对外部资源的控制以及设计阶段支援。

对外部资源的控制

IComponent 介面扩充 System.IDisposable 介面,在後者的约定中有一个名为 Dispose 的方法。在它的 Dispose 方法实作 (Implementation) 中,元件必须明确地释放外部资源。这样就提供一种释放资源的决定性方式,不同於透过记忆体清除发生的预设非决定性清除。开发者必须传播 Dispose 到整个 Containment 阶层架构,以确保元件的子系也会释放资源。此外,衍生的元件必须叫用其基底类别 (Base Class) 的 Dispose 方法。

**注意 **即使透过 Dispose 提供对资源的明确控制,您仍然应该透过完成项 (解构函式) 提供隐含的清除,以防止使用者万一没有对您元件呼叫 Dispose 时,造成资源的永久性遗漏。

下列范例所示是在基底元件和衍生元件中实作 Dispose 的模式。

// [C#]
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.
}
' [Visual Basic]
' 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 .NET。您可以将元件加入至 Visual Studio .NET 的工具箱、可将其拖放到表单上,也可以在设计介面上进行处理。请注意,IComponent 型别的基底设计阶段支援是内建於 .NET Framework;元件开发人员不必执行额外的工作,就可以使用基底设计阶段的功能。

如需设计阶段支援的详细资讯,请参阅元件的设计阶段属性增强设计阶段支援

装载元件

元件可以设置 (装载) 於容器 (Container) 之内 (本主题稍後会予定义)。当元件被设置时,它是透过它的站台 (本主题稍後会予定义) 与容器互动,并且能够透过站台从它的容器查询和取得服务。为确保容器被拆除时资源会被释放,容器必须实作 IDisposable 介面。容器在它的 Dispose 方法实作中,必须释放它所持有的所有资源,并且叫用它所包含每一个元件的 Dispose 方法。

Containment 是逻辑性的,不需要具有视觉化的表示方式。设置资料库元件的中介层 (Middle Tier) 容器就是非视觉化 Containment 的范例。视觉化的 Containment 会在 Visual Studio .NET 的 Windows Form 设计工具和 Web Form 设计工具中看见。视觉化的设计介面是一个容器,可装载表单元件 (在 Web Form 中是 Page 元件)。

封送处理元件

元件可分为可远端处理者及不可远端处理者。可远端处理的元件是以传址 (By Reference) 或传值 (By Value) 方式封送处理。封送处理包括跨界限传送物件,所谓界限包括应用程式定义域 (轻量处理序)、处理序和电脑。当物件以传址方式封送处理时,会建立对该物件进行远端呼叫的 Proxy。当物件以传值方式封送处理时,会跨相关界限传送物件的序列化复本。

封装系统资源、大型或以单一执行个体 (Instance) 存在的可远端处理元件应该以传址方式封送处理。以传址方式封送处理之元件的基底类别为 System.ComponentModel.Component。这个基底类别会实作 IComponent 并且是从 MarshalByRefObject 衍生。.NET Framework 类别库 (Class Library) 中的许多元件都是从 Component 衍生而来,包括 System.Windows.Forms.Control (Windows Form 控制项的基底类别)、System.Web.Services.WebService (使用 ASP.NET 所建立的 XML Web Service 的基底类别) 和 System.Timers.Timer (产生递回事件的类别)。

只存有状态的可远端处理元件应该以传值方式封送处理。以传值方式封送处理之元件的基底类别为 System.ComponentModel.MarshalByValueComponent。这个基底类别会实作 IComponent 并且是从 Object 衍生。.NET Framework 类别库中只有少数几个元件是从 MarshalByValueComponent 衍生。所有这类元件都在 System.Data 命名空间 (Namespace) 之内 (DataColumnDataSetDataTableDataViewDataViewManager)。

**注意 **以传值和传址方式封送处理之物件的基底类别分别为 ObjectMarshalByRefObject,但是对应的衍生类别 (Derived Class) 则命名为 MarshalByValueComponentComponent。这种命名配置所依据的逻辑是,越常使用的型别要具有越简单的名称。

如果元件不需要远端处理,就不要从基底实作衍生 Component,而是直接实作 IComponent

如需物件远端处理的详细资讯,请参阅 .NET 远端处理概观

控制项

控制项是一种提供 (或启用) 使用者介面 (UI) 能力的元件。.NET Framework 为控制项提供了两个基底类别:一个是用户端 Windows Form 控制项,另一个是 ASP.NET 伺服器控制项。它们是 System.Windows.Forms.ControlSystem.Web.UI.Control。.NET Framework 类别库中的所有控制项都是从这两个类别直接或间接衍生。System.Windows.Forms.Control 是从 Component 衍生,而且它本身提供 UI 能力。System.Web.UI.Control 会实作 IComponent,而且会提供很容易在上面加入 UI 功能的基础结构。

**注意 **每个控制项都是一个元件,但每个元件不一定是控制项。

容器和站台

如果您要开发 Windows Form 或 Web Form 网页 (ASP.NET 网页) 的元件和控制项,您不需实作容器或站台。Windows Form 和 Web Form 的设计工具,就相当於Windows Form 和 ASP.NET 伺服器控制项的容器。容器可对设置於它们之内的元件和控制项提供服务。在设计阶段,控制项是设置在设计工具中,并且从设计工具取得服务。为完整起见,仅将容器和站台的定义列述如下。

容器 : 容器是实作 System.ComponentModel.IContainer 介面的类别,或者从实作这个介面之类别衍生的类别。容器在逻辑上可包含一个或多个被称为容器子元件的元件。

网站 : 站台是实作 System.ComponentModel.ISite 介面的类别,或者从实作这个介面之类别衍生的类别。站台是由容器提供,用来管理其子元件并且与它们通讯。通常,一个容器和一个站台会实作为一个单元。

请参阅

属性概观 | 元件的设计阶段属性 | 开发 Windows Form 控制项 | 开发 ASP.NET 伺服器控制项 | 增强设计阶段支援

转载自:http://msdn.microsoft.com/library/cht/default.asp?url=/library/CHT/cpguide/html/cpconclassvscomponentvscontrol.asp