Vergleich von Klassen, Komponenten und Steuerelementen
In diesem Thema werden die Begriffe Komponente und Steuerelement definiert. Mithilfe dieser Informationen können Sie entscheiden, wann Sie eine Klasse implementieren, die eine Komponente bzw. ein Steuerelement ist.
Tipp
In diesem Thema werden Windows Forms und ASP.NET-Klassen behandelt. Diese Ausführungen gelten nicht für WPF-Klassen. Informationen zum Erstellen von WPF-Steuerelementen finden Sie unter Übersicht über das Erstellen von Steuerelementen.
Die folgende Liste enthält allgemeine Richtlinien für die Implementierung.
Wenn die Klasse externe Ressourcen verwendet, jedoch in keiner Entwurfsoberfläche eingesetzt wird, implementieren Sie System.IDisposable, oder leiten Sie von einer Klasse ab, durch die IDisposable direkt oder indirekt implementiert wird.
Wenn die Klasse in einer Entwurfsoberfläche (z. B. dem Windows Forms- oder Web Forms-Designer) verwendet werden soll, implementieren Sie System.ComponentModel.IComponent, oder leiten Sie von einer Klasse ab, durch die IComponent direkt oder indirekt implementiert wird. Beachten Sie, dass IDisposable durch IComponent erweitert wird, sodass ein IComponent-Typ immer einem IDisposable-Typ entspricht. Obwohl ein IComponent-Typ geringfügig mehr Leistung beansprucht als ein IDisposable-Typ, der kein IComponent-Typ ist, wird dieser Nachteil normalerweise dadurch ausgeglichen, dass ein IComponent-Typ zur Entwurfs- und zur Laufzeit platziert werden kann. (Diese Fähigkeit wird weiter unten in diesem Thema erläutert.)
Falls Sie eine entwurfsfähige (in einer Entwurfsoberfläche verwendete) Klasse benötigen, die als Verweis gemarshallt werden kann, können Sie von System.ComponentModel.Component ableiten. Component ist die Basisimplementierung eines als Verweis gemarshallten IComponent-Typs.
Falls Sie eine entwurfsfähige Klasse benötigen, die als Wert gemarshallt werden kann, können Sie von System.ComponentModel.MarshalByValueComponent ableiten. MarshalByValueComponent ist die Basisimplementierung eines als Wert gemarshallten IComponent-Typs.
Wenn Sie einen IComponent-Typ in die Objektmodellhierarchie einführen möchten und aufgrund von Einzelvererbung nicht von einer Basisimplementierung wie Component oder MarshalByValueComponent ableiten können, implementieren Sie IComponent.
Falls Sie eine entwurfsfähige Klasse benötigen, die eine Benutzeroberfläche bereitstellt, handelt es sich bei der Klasse um ein Steuerelement. Steuerelemente müssen direkt oder indirekt entweder von der System.Windows.Forms.Control-Basisklasse oder der System.Web.UI.Control-Basisklasse abgeleitet werden.
Tipp
Wenn die Klasse weder entwurfsfähig ist noch externe Ressourcen umfasst, sind die Typen IComponent oder IDisposable nicht erforderlich.
Im Folgenden die Definitionen für Komponenten, Steuerelemente, Container und Sites.
Komponente
Eine Komponente ist in .NET Framework eine Klasse, die die System.ComponentModel.IComponent-Schnittstelle implementiert oder die direkt oder indirekt von einer Klasse abgeleitet ist, die IComponent implementiert. Bei der Programmierung ist eine Komponente i. A. ein Objekt, das wiederverwendet werden kann und mit anderen Objekten interagieren kann. Eine .NET Framework-Komponente entspricht diesen allgemeinen Anforderungen und bietet zusätzliche Features, z. B. Steuerung externer Ressourcen und Unterstützung zur Entwurfszeit.
Steuern externer Ressourcen
Die IComponent-Schnittstelle stellt eine Erweiterung der IDisposable-Schnittstelle dar, die eine Methode mit dem Namen Dispose in ihrem Kontrakt aufweist. Eine Komponente muss bei der Implementierung der Dispose-Methode externe Ressourcen explizit freigeben. Dies ermöglicht eine deterministische Freigabe von Ressourcen, im Gegensatz zum nicht deterministischen Bereinigen durch die Garbage Collection (Standardeinstellung). Entwickler müssen Disposeinnerhalb der gesamten Kapselungshierarchie weitergeben, um sicherzustellen, dass untergeordnete Elemente einer Komponente ebenfalls Ressourcen freigeben. Außerdem muss eine abgeleitete Komponente die Dispose-Methode der zugehörigen Basisklasse aufrufen.
Tipp
Auch wenn Sie mit Dispose die explizite Steuerung von Ressourcen bereitstellen, sollten Sie immer das implizite Bereinigen durch den Finalizer (Destruktor) ermöglichen, damit Ressourcen nicht dauerhaft Speicherverluste verursachen, wenn ein Benutzer nicht Dispose für die Komponente aufruft.
Das folgende Beispiel veranschaulicht das Muster für das Implementieren von Dispose in einer Basiskomponente und in einer abgeleiteten Komponente.
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
Unterstützung zur Entwurfszeit
Ein wichtiges Feature der Komponenten in .NET Framework besteht darin, dass diese entwurfsfähig sind, d. h., dass eine Klasse, die eine Komponente ist, in einer RAD-Umgebung (Rapid Application Development) wie Visual Studio verwendet werden kann. Eine Komponente kann der Toolbox von Visual Studio hinzugefügt, per Drag & Drop in ein Formular eingefügt und in einer Entwurfsoberfläche geändert werden. Beachten Sie, dass die Basisunterstützung zur Entwurfszeit für IComponent-Typen in .NET Framework integriert ist; ein Komponentenentwickler muss daher keine zusätzlichen Schritte unternehmen, um die Vorteile der Basisfunktionalität zur Entwurfszeit nutzen zu können.
Weitere Informationen zur Unterstützung während der Entwurfszeit finden Sie unter Entwurfszeitattribute für Komponenten und Erweitern der Entwurfszeitunterstützung.
Hosten einer Komponente
Eine Komponente kann in einem Container (Definition weiter unten in diesem Thema) platziert (gehostet) werden. Wenn eine Komponente platziert wird, interagiert diese mit dem Container über die Site (Definition weiter unten in diesem Thema) und kann über die Site Dienste vom Container abfragen und abrufen. Um sicherzustellen, dass Ressourcen bei der Auflösung eines Containers freigegeben werden, muss der Container die IDisposable-Schnittstelle implementieren. In der Implementierung der Dispose-Methode muss der Container alle beanspruchten Ressourcen freigeben und die Dispose-Methode jeder enthaltenen Komponente aufrufen.
Die Kapselung ist logisch und muss nicht visuell dargestellt werden. Ein Container der mittleren Ebene, in dem Datenbankkomponenten platziert sind, stellt ein Beispiel der nicht visuellen Kapselung dar. Beispiele für die visuelle Kapselung finden Sie im Windows Forms-Designer und im Web Forms-Designer in Visual Studio. Die visuelle Entwurfsoberfläche ist ein Container, der die Formularkomponente hostet (in Web Forms die Seitenkomponente).
Marshallen einer Komponente
Komponenten können remotefähig oder nicht remotefähig sein. Remotefähige Komponenten werden als Verweis oder als Wert gemarshallt. Das Marshallen beinhaltet das bereichsübergreifende Senden von Objekten zwischen Anwendungsdomänen (einfachen Prozessen), Prozessen und sogar Computern. Beim Marshallen eines Objekts als Verweis wird ein Proxy erstellt, der Remoteaufrufe des Objekts durchführt. Beim Marshallen eines Objekts anhand des Werts wird eine serialisierte Kopie des Objekts über die jeweilige Grenze hinweg gesendet.
Remotefähige Komponenten, die umfangreiche Systemressourcen kapseln oder die als einzelne Instanzen vorliegen, sollten als Verweis gemarshallt werden. Die Basisklasse für Komponenten, die als Verweis gemarshallt werden, lautet System.ComponentModel.Component. Diese Basisklasse implementiert IComponent und wird von MarshalByRefObject abgeleitet. Zahlreiche Komponenten in der .NET Framework-Klassenbibliothek werden von Component abgeleitet, einschließlich System.Windows.Forms.Control (der Basisklasse für Windows Forms-Steuerelemente), System.Web.Services.WebService (der Basisklasse für die mit ASP.NET erstellten XML-Webdienste) und System.Timers.Timer (einer Klasse, die Ereignisserien generiert).
Remotefähige Komponenten, die nur den Zustand speichern, sollten als Wert gemarshallt werden. Die Basisklasse für Komponenten, die als Wert gemarshallt werden, lautet System.ComponentModel.MarshalByValueComponent. Diese Basisklasse implementiert IComponent und wird von Object abgeleitet. Nur einige Komponenten in der .NET Framework-Klassenbibliothek werden von MarshalByValueComponent abgeleitet. Alle diese Komponenten sind im System.Data-Namespace (DataColumn, DataSet, DataTable, DataView und DataViewManager) enthalten.
Tipp
Die Basisklassen für als Wert bzw. Verweis gemarshallte Objekte lauten Object und MarshalByRefObject, die entsprechenden abgeleiteten Klassen heißen jedoch MarshalByValueComponent und Component. Bei der Benennung wurde darauf geachtet, dass der häufiger verwendete Typ den einfacheren Namen erhält.
Wenn eine Komponente nicht remote verwendet werden soll, sollten Sie diese nicht von den Basisimplementierungen für Component ableiten, sondern stattdessen IComponent direkt implementieren.
Steuerelement
Ein Steuerelement ist eine Komponente, die Funktionen der Benutzeroberfläche bereitstellt oder aktiviert. .NET Framework bietet zwei Basisklassen für Steuerelemente: eine für Windows Forms-Steuerelemente auf der Clientseite und die andere für ASP.NET-Serversteuerelemente. Diese lauten System.Windows.Forms.Control und System.Web.UI.Control. Alle Steuerelemente in der .NET Framework-Klassenbibliothek werden direkt oder indirekt von diesen zwei Klassen abgeleitet. System.Windows.Forms.Control wird von Component abgeleitet und bietet selbst Benutzeroberflächenfunktionen. System.Web.UI.Control implementiert IComponent und stellt die Infrastruktur bereit, unter der Benutzeroberflächenfunktionalität auf einfache Weise bereitgestellt werden kann.
Tipp
Jedes Steuerelement ist eine Komponente, aber nicht jede Komponente ist ein Steuerelement.
Container und Site
Wenn Sie Komponenten und Steuerelemente für Windows Forms- oder Web Forms-Seiten (ASP.NET-Seiten) entwickeln, müssen Sie keine Container oder Sites implementieren. Die Designer für Windows Forms und Web Forms sind Container für Windows Forms- und für ASP.NET-Serversteuerelemente. Container stellen Dienste für die Komponenten und Steuerelemente bereit, die in ihnen platziert sind. Zur Entwurfszeit werden Steuerelemente im Designer platziert, die Dienste vom Designer abrufen. Im Folgenden finden Sie die Definitionen von Container und Site.
Container
Ein Container ist eine Klasse, die die System.ComponentModel.IContainer-Schnittstelle implementiert oder die von einer Klasse abgeleitet wird, die diese Schnittstelle implementiert. Ein Container enthält aus logischer Sicht eine oder mehrere Komponenten, die als untergeordnete Komponenten des Containers bezeichnet werden.Site
Eine Site ist eine Klasse, die die System.ComponentModel.ISite-Schnittstelle implementiert oder die von einer Klasse abgeleitet wird, die diese Schnittstelle implementiert. Sites werden von einem Container bereitgestellt, um dessen untergeordnete Komponenten zu verwalten und mit diesen zu kommunizieren. Normalerweise werden ein Container und eine Site als Einheit implementiert.
Siehe auch
Konzepte
Entwurfszeitattribute für Komponenten
Weitere Ressourcen
Entwickeln benutzerdefinierter Windows Forms-Steuerelemente mit .NET Framework
Entwickeln von benutzerdefinierten ASP.NET-Serversteuerelementen
Erweitern der Entwurfszeitunterstützung
Änderungsprotokoll
Datum |
Versionsgeschichte |
Grund |
---|---|---|
Juli 2010 |
Hinweis hinzugefügt, dass in diesem Thema nur Windows Forms behandelt wird. |
Kundenfeedback. |