Поделиться через


Выбор между классом, компонентом и элементом управления

В этом разделе приводится определение компонента и элемента управления; представленное здесь обсуждение должно помочь решить, когда следует реализовывать класс, являющийся компонентом или элементом управления.

Примечание

В этом разделе описываются классы Windows Forms и ASP.NET.В этом разделе не описываются классы WPF. Дополнительные сведения о создании элементов управления WPF см. в разделе Общие сведения о разработке управления.

Следующий список содержит общие принципы реализации.

  • Если класс использует внешние ресурсы, но не будет использован на поверхности разработки, он должен реализовывать интерфейс System.IDisposable или быть производным от класса, который непосредственно или косвенно реализует IDisposable.

  • Если класс будет использован на поверхности разработки (например, в конструкторе Windows Forms или Web Forms), он должен реализовывать интерфейс 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 является то, что они поддерживают проектирование. Это означает, что класс-компонент может быть использован в среде быстрой разработки приложений, например в Visual Studio. Компонент можно добавить на панель элементов Visual Studio или перетащить на форму. С ним также можно работать на поверхности разработки. Обратите внимание, что базовая поддержка типов IComponent во время разработки встроена в среду .NET Framework; разработчикам компонентов не нужно прикладывать дополнительные усилия, чтобы воспользоваться преимуществами базовых функций, поддерживаемых во время разработки.

Дополнительные сведения о поддержке средств времени разработки см. в разделах Атрибуты времени разработки для компонентов и Расширение поддержки времени разработки.

Размещение компонентов

Компонент может быть расположен (размещен) в контейнере (понятие будет определено позже в этом разделе). Если компонент размещен на подложке, он взаимодействует с контейнером через эту подложку (понятие будет определено позднее в этом разделе), а также может запрашивать и получать через нее службы своего контейнера. Чтобы обеспечить освобождение ресурсов в случае уничтожения контейнера, контейнер должен реализовывать интерфейс IDisposable. В своей реализации метода Dispose контейнер должен освобождать все используемые им ресурсы, а также вызвать метод Dispose для всех содержащихся в нем компонентов.

Вложенность обеспечивается на логическом уровне и может не иметь визуального представления. Контейнер среднего уровня, содержащий компоненты базы данных, — пример вложенности, не имеющей визуального представления. Визуальная вложенность наблюдается в конструкторе Windows Forms и конструкторе Web Forms среды Visual Studio. Визуальная поверхность разработки — это контейнер, содержащий компонент формы (в случае конструктора Web Forms — компонент страницы).

Маршалинг компонентов

Компоненты могут поддерживать или не поддерживать удаленное взаимодействие. Компоненты, которые его поддерживают, маршалируются по ссылке или по значению. Процесс маршалинга включает в себя пересылку объектов за границы таких сущностей, как Домены приложений (облегченные процессы), процессы и даже машины. Если маршалинг выполняется по ссылке, создается прокси, который осуществляет удаленные обращения к объекту. Если маршалинг выполняется по значению, сериализованная копия объекта посылается через соответствующую границу.

Маршалинг поддерживающих удаленное взаимодействие компонентов, которые инкапсулируют системные ресурсы, имеют большой размер или существуют как отдельные экземпляры, должна выполняться по ссылке. Базовым классом компонентов, маршалинг которых выполняется по ссылке, является System.ComponentModel.Component. Этот базовый класс реализует интерфейс IComponent и наследует от класса MarshalByRefObject. Многие компоненты библиотеки классов .NET Framework происходят от класса Component, включая System.Windows.Forms.Control (базовый класс для элементов управления Windows Forms), System.Web.Services.WebService (базовый класс для веб-служб XML, созданных с использованием ASP.NET) и System.Timers.Timer (класс, создающий повторяющиеся события).

Маршалинг поддерживающих удаленное взаимодействие компонентов, которые просто сохраняют состояние, должна выполняться по значению. Базовым классом компонентов, маршалинг которых выполняется по значению, является System.ComponentModel.MarshalByValueComponent. Этот базовый класс реализует интерфейс IComponent и наследует от класса Object. Только некоторые компоненты библиотеки классов .NET Framework происходят от класса MarshalByValueComponent. Все такие компоненты принадлежать пространству имен System.Data (DataColumn, DataSet, DataTable, DataView и DataViewManager).

Примечание

Базовыми классами для объектов, маршалируемыхых по значению и по ссылке, являются Object и MarshalByRefObject соответственно, однако имена соответствующих им производных классов — MarshalByValueComponent и Component.Логика именования состоит в том, что чаще используемый тип имеет более простое имя.

Если удаленное взаимодействие компонента не предполагается, не следует наследовать его от базовой реализации класса Component; вместо этого следует непосредственно реализовать интерфейс IComponent.

Элемент управления

Элемент управления — это компонент, предоставляющий (или обеспечивающий) возможности пользовательского интерфейса. В среде .NET Framework предусмотрено два базовых класса для элементов управления: один для клиентских элементов управления Windows Forms, а другой для серверных элементов управления ASP.NET. Этими классами являются System.Windows.Forms.Control и System.Web.UI.Control. Все элементы управления библиотеки классов .NET Framework непосредственно или косвенно происходят от этих двух классов. System.Windows.Forms.Control происходит от класса Component и сам предоставляет возможности пользовательского интерфейса. Класс System.Web.UI.Control реализует интерфейс IComponent и предоставляет инфраструктуру, позволяющую легко добавить возможности пользовательского интерфейса.

Примечание

Любой элемент управления является компонентом, но обратное неверно.

Контейнер и подложка

При разработке компонентов и элементов управления для Windows Forms или страниц Web Forms (страниц ASP.NET) нет необходимости реализовывать контейнеры или подложки. Конструкторы Windows Forms и Web Forms являются контейнерами для элементов управления Windows Forms и серверных элементов управления ASP.NET. Контейнеры предоставляют службы компонентам и элементам управления, расположенным в них. Во время разработки элементы управления располагаются в конструкторе и получают доступ к его службам. В завершение приведем определения контейнера и подложки.

  • Container
    Контейнер — это класс, который реализует интерфейс System.ComponentModel.IContainer, либо прямо или косвенно наследует от класса, реализующего этот интерфейс. Логически контейнер содержит один или несколько компонентов, называемых дочерними компонентами контейнера.

  • Site
    Подложка — это класс, который реализует интерфейс System.ComponentModel.ISite, либо прямо или косвенно наследует от класса, реализующего этот интерфейс. Подложки предоставляются контейнером для управления его дочерними компонентами и доступа к ним. Обычно контейнер и подложка реализуются как одно целое.

См. также

Основные понятия

Общие сведения о свойствах

Атрибуты времени разработки для компонентов

Другие ресурсы

Разработка пользовательских элементов управления Windows Forms в .NET Framework

Разработка пользовательских серверных элементов управления ASP.NET

Расширение поддержки времени разработки

Журнал изменений

Дата

Журнал

Причина

Июль 2010

Добавлено примечание о том, что в этом разделе описывается только Windows Forms.

Обратная связь от клиента.