Compartir a través de


Clase frente a componente y frente a control

Actualización: noviembre 2007

En este tema se definen los términos componente y control; estas explicaciones le ayudarán a decidir cuándo debe implementar una clase que sea un componente o un control.

La siguiente lista incluye exhaustivas instrucciones para los implementadores.

A continuación figuran las definiciones de componente, control, contenedor y sitio.

Componente

En .NET Framework, un componente es una clase que implementa la interfaz System.ComponentModel.IComponent o se deriva directa o indirectamente de una clase que implementa IComponent. En programación, el término componente se utiliza normalmente para objetos que se pueden volver a utilizar y que pueden interactuar con otros objetos. Un componente de .NET Framework cumple esos requisitos generales y, además, dispone de características como control sobre recursos externos y compatibilidad en tiempo de diseño.

Control sobre recursos externos

La interfaz IComponent extiende la interfaz IDisposable, que tiene un método denominado Dispose en su contrato. En su implementación del método Dispose, un componente debe liberar los recursos externos de forma explícita. Esta es una manera determinista de liberar recursos, en contraste con la limpieza no determinista predeterminada que sucede durante la recolección de elementos no utilizados. Los desarrolladores deben propagar Disposepor toda la jerarquía de la contención para asegurarse de que los elementos secundarios de un componente también liberan los recursos. Además, un componente derivado debe invocar al método Dispose de su clase base.

Nota:

Aunque proporcione control explícito sobre los recursos mediante Dispose, siempre debe realizar una limpieza implícita mediante el finalizador (destructor) para evitar que los recursos se pierdan de forma permanente si un usuario no llama a Dispose en el componente.

En el siguiente ejemplo se muestra el modelo de implementación de Dispose en un componente base y en un componente derivado.

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

Compatibilidad en tiempo de diseño

Una característica importante de los componentes de .NET Framework es que se pueden diseñar; es decir, que una clase que es un componente puede utilizarse en un entorno de programación rápida de aplicaciones (RAD) como Visual Studio. Un componente se puede agregar al cuadro de herramientas de Visual Studio, se puede arrastrar y colocar en un formulario, y se puede manipular en una superficie de diseño. Observe que .NET Framework incorpora compatibilidad en tiempo de diseño con los tipos IComponent; un desarrollador de componentes no tiene que realizar ningún trabajo adicional para aprovechar la funcionalidad base en tiempo de diseño.

Para obtener más información sobre la compatibilidad en tiempo de diseño, vea Atributos en tiempo de diseño para componentes y Ampliar compatibilidad en tiempo de diseño.

Alojar un componente

Un componente se puede ubicar (alojar) en un contenedor (definido más adelante en este tema). Cuando se ubica un componente, interactúa con el contenedor a través de su sitio (definido más adelante en este tema), y puede consultar y obtener servicios de su contenedor a través del sitio. Para asegurarse de que los recursos se liberan cuando el contenedor deje de usarse, el contenedor debe implementar la interfaz IDisposable. En su implementación del método Dispose, un contenedor debe liberar todos los recursos que mantiene e invocar al método Dispose de cada uno de los componentes que contiene.

La contención es lógica y no necesita tener representación visual. Un ejemplo de contención no visual es un contenedor de nivel medio que aloja componentes de base de datos. La contención visual se ve en los diseñadores de Windows Forms y Web Forms de Visual Studio. La superficie de diseño visual es un contenedor que aloja el componente de formulario (en formularios Web Forms, el componente de página).

Calcular las referencias de un componente

Los componentes pueden ser de uso remoto o de uso no remoto. Las referencias de los componentes de uso remoto se calculan por referencia o por valor. El cálculo de referencias implica el envío de objetos a través de límites como dominios de aplicación (procesos ligeros), procesos e incluso equipos. Cuando las referencias de un objeto se calculan por referencia, se crea un proxy que realiza llamadas remotas al objeto. Cuando las referencias de un objeto se calculan por valor, se envía una copia serializada del objeto a través de los límites relevantes.

Las referencias de los componentes de uso remoto que encapsulan recursos del sistema, que son grandes o que existen como instancias únicas, se deben calcular por referencia. La clase base de los componentes cuyas referencias se calculan por referencia es System.ComponentModel.Component. Esta clase base implementa la interfaz IComponent y deriva de MarshalByRefObject. Muchos componentes de la biblioteca de clases de .NET Framework se derivan de Component, incluidos System.Windows.Forms.Control (la clase base de los controles de formularios Windows Forms), System.Web.Services.WebService (la clase base de los servicios Web XML creados mediante ASP.NET) y System.Timers.Timer (una clase que genera eventos recurrentes).

Las referencias de los componentes de uso remoto que sólo guardan un estado se deben calcular por valor. La clase base de los componentes cuyas referencias se calculan por valor es System.ComponentModel.MarshalByValueComponent. Esta clase base implementa la interfaz IComponent y deriva de Object. Sólo unos pocos componentes de la biblioteca de clases de .NET Framework derivan de MarshalByValueComponent. Todos esos componentes están en el espacio de nombres System.Data (DataColumn, DataSet, DataTable, DataView y DataViewManager).

Nota:

Las clases base de los objetos cuyas referencias se calculan por valor y por referencia son Object y MarshalByRefObject, respectivamente, pero las clases derivadas correspondientes se denominan MarshalByValueComponent y Component. La razón de la utilización de este esquema de nombres es que el tipo utilizado más habitualmente tiene el nombre más sencillo.

Si un componente no va a ser remoto, no debe derivarse de las implementaciones base de Component; en su lugar, implemente IComponent directamente.

Para obtener más información acerca de la interacción remota de objetos, vea Información general de .NET Remoting.

Control

Un control es un componente que proporciona o habilita funciones de la interfaz de usuario. .NET Framework dispone de dos clases base para controles: una para controles de formularios Windows Forms del cliente y otra para controles de servidor de ASP.NET. Éstas son System.Windows.Forms.Control y System.Web.UI.Control. Todos los controles de la biblioteca de clases de .NET Framework derivan directa o indirectamente de estas dos clases. System.Windows.Forms.Control deriva de Component y proporciona funciones de interfaz de usuario. System.Web.UI.Control implementa IComponent y proporciona la infraestructura en la cual es fácil agregar funcionalidad de interfaz de usuario.

Nota:

Todos los controles son componentes, pero no al revés.

Contenedor y sitio

Si va a programar componentes y controles para formularios Windows Forms o para páginas de formularios Web Forms (páginas de ASP.NET), no es necesario implementar contenedores o sitios. Los diseñadores de Windows Forms y de formularios Web Forms son contenedores de formularios Windows Forms y de los controles de servidor de ASP.NET. Los contenedores proporcionan servicios a los componentes y controles alojados en ellos. En tiempo de diseño, los controladores se alojan en el diseñador y obtienen servicios del mismo. Para ofrecer más detalles, a continuación se ofrecen las definiciones de contenedor y sitio.

  • Container
    Un contenedor es una clase que implementa la interfaz System.ComponentModel.IContainer o que deriva de una clase que implementa esta interfaz. De forma lógica, un contenedor contiene uno o varios componentes, que se denominan componentes secundarios del contenedor.

  • Site
    Un sitio es una clase que implementa la interfaz System.ComponentModel.ISite o que deriva de una clase que implementa esta interfaz. Un contenedor proporciona los sitios para administrar y comunicarse con sus componentes secundarios. Normalmente, un contenedor y un sitio se implementan como una unidad.

Vea también

Conceptos

Información general sobre propiedades

Atributos en tiempo de diseño para componentes

Otros recursos

Desarrollar controles personalizados de formularios Windows Forms con .NET Framework

Desarrollar controles de servidor ASP.NET personalizados

Ampliar compatibilidad en tiempo de diseño