Confronto tra classe, componente e controllo
Aggiornamento: novembre 2007
Questo argomento fornisce le definizioni di componente e controllo. Le informazioni riportate possono essere utilizzate per determinare se utilizzare una classe componente o controllo.
Nell'elenco che segue vengono fornite indicazioni di massima per l'implementazione.
Se la propria classe fa uso di risorse esterne ma non verrà utilizzata su un'area di progettazione, implementare System.IDisposable o derivare da una classe che implementa direttamente o indirettamente IDisposable.
Se la propria classe verrà utilizzata su un'area di progettazione, quale la finestra di progettazione di Windows Forms o di Web Form, implementare System.ComponentModel.IComponent o derivare da una classe che implementa direttamente o indirettamente IComponent. IComponent estende IDisposable, pertanto un tipo IComponent è sempre un tipo IDisposable. Il tipo IComponent offre prestazioni leggermente ridotte rispetto a un tipo IDisposable che non è IComponent. Tale svantaggio è solitamente compensato dalla possibilità di posizionare il tipo IComponent sia in fase di progettazione che in fase di esecuzione. Il posizionamento è descritto più avanti in questo argomento.
Per ottenere una classe che possa essere utilizzata su un'area di progettazione e di cui venga eseguito il marshalling per riferimento, derivare da System.ComponentModel.Component. Component rappresenta l'implementazione di base di un tipo IComponent di cui è possibile eseguire il marshalling per riferimento.
Per ottenere una classe che possa essere utilizzata su un'area di progettazione e di cui venga eseguito il marshalling per valore, derivare da System.ComponentModel.MarshalByValueComponent. MarshalByValueComponent rappresenta l'implementazione di base di un tipo IComponent di cui è possibile eseguire il marshalling per valore.
Se si desidera inserire un tipo IComponent nella gerarchia del modello a oggetti e non è possibile derivare da un'implementazione di base quale Component o MarshalByValueComponent a causa dell'ereditarietà singola, implementare IComponent.
Una classe che può essere utilizzata su un'area di progettazione e dispone di un'interfaccia utente è un controllo. I controlli devono derivare direttamente o indirettamente da una delle classi di controlli di base: System.Windows.Forms.Control o System.Web.UI.Control.
Nota: Se una classe non può essere utilizzata su un'area di progettazione né utilizza risorse esterne, non occorre un tipo IComponent o IDisposable.
In seguito sono riportate le definizioni di componente, controllo, contenitore e sito.
Componente
In .NET Framework un componente è una classe che implementa l'interfaccia System.ComponentModel.IComponent o che deriva direttamente o indirettamente da una classe che implementa IComponent. In programmazione il termine componente è solitamente utilizzato per indicare un oggetto riutilizzabile in grado di interagire con altri oggetti. Un componente .NET Framework, oltre a soddisfare tali requisiti generali, fornisce funzionalità quali il controllo di risorse esterne e il supporto della fase di progettazione.
Controllo di risorse esterne
L'interfaccia IComponent estende l'interfaccia IDisposable, il cui contratto include un metodo denominato Dispose. Nella nuova implementazione del metodo Dispose un componente deve rilasciare le risorse esterne in modo esplicito. In tal modo è possibile liberare le risorse in modo deterministico, diversamente da quanto avviene con il rilascio predefinito non deterministico ottenibile tramite Garbage Collection. Gli sviluppatori devono propagare Disposein tutta la gerarchia di contenimento, affinché anche i figli del componente liberino le proprie risorse. È inoltre necessario che gli eventuali componenti derivati invochino il metodo Dispose della propria classe base.
Nota: |
---|
Anche se Dispose fornisce il controllo esplicito sulle risorse, è preferibile che lo sviluppatore provveda a liberarle comunque in modo implicito tramite il finalizzatore (distruttore), così da evitare la perdita permanente di risorse che si verifica se un utente non chiama Dispose sul componente. |
Nell'esempio che segue viene illustrata la tecnica per l'implementazione di Dispose in un componente di base e in un componente derivato.
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
Supporto della fase di progettazione
Un'importante funzionalità dei componenti di .NET Framework è quella che li rende manipolabili in fase di progettazione. In altre parole, una classe che riveste il ruolo di componente può essere utilizzata in un ambiente per lo sviluppo rapido di applicazioni (RAD, Rapid Application Development) quale Visual Studio. I componenti possono essere aggiunti alla casella degli strumenti di Visual Studio, trascinati e rilasciati su un form e modificati su una superficie di progettazione. Si noti che il supporto di base per la fase di progettazione per i tipi IComponent è incorporato in .NET Framework. La fruizione di tale supporto non richiede allo sviluppatore di componenti alcun intervento aggiuntivo.
Per ulteriori informazioni sul supporto di base in fase di progettazione, vedere Attributi per componenti in fase di progettazione e Estensione del supporto in fase di progettazione.
Hosting di un componente
È possibile collocare i componenti in un contenitore (definito più avanti in questo argomento). Quando il componente viene posizionato, interagisce con il contenitore tramite il relativo sito (definito più avanti in questo capitolo) e può interrogarlo e richiederne i servizi. Per garantire il rilascio delle risorse all'atto della dismissione del contenitore, occorre che quest'ultimo implementi l'interfaccia IDisposable. Nella propria implementazione del metodo Dispose è necessario che il contenitore rilasci tutte le risorse impegnate e invochi il metodo Dispose di ciascuno dei componenti in esso contenuti.
Il contenimento è logico e non richiede una rappresentazione visiva. Un contenitore del livello intermedio che ospita componenti per database costituisce un esempio di contenimento non visivo. Il contenimento visivo viene rappresentato nella finestra di progettazione di Windows Form e di Web Form di Visual Studio. L'area di progettazione è un contenitore che ospita il componente form (in Web Form, il componente pagina).
Marshalling di un componente
È possibile distinguere tra componenti gestibili da remoto o meno. Il marshalling dei componenti gestibili da remoto viene effettuato per riferimento o per valore. Il marshalling riguarda l'invio di oggetti attraverso limiti quali quelli delineati dai domini applicazione (processi leggeri), dai processi e dai computer. Quando il marshalling di un oggetto viene effettuato per riferimento, viene creato un proxy che effettua chiamate remote all'oggetto. Quando il marshalling di un oggetto viene effettuato per valore, una copia serializzata dell'oggetto viene inviata oltre i limiti del caso.
Il marshalling dei componenti gestibili da remoto che incapsulano risorse di sistema (di grandi dimensioni) o che esistono come istanza singola deve essere effettuato per riferimento. La classe di base dei componenti il cui marshalling viene effettuato per riferimento è System.ComponentModel.Component. Tale classe base implementa IComponent e deriva da MarshalByRefObject. Molti componenti della libreria di classi .NET Framework derivano da Component, compresi System.Windows.Forms.Control (la classe base dei controlli Windows Form), System.Web.Services.WebService (la classe base dei servizi Web XML creati utilizzando ASP.NET) e System.Timers.Timer (una classe che genera eventi ricorrenti).
Il marshalling dei componenti gestibili da remoto che detengono solo uno stato deve essere effettuato per valore. La classe di base dei componenti il cui marshalling viene effettuato per valore è System.ComponentModel.MarshalByValueComponent. Tale classe base implementa IComponent e deriva da Object. I pochi componenti della libreria di classi .NET Framework che derivano da MarshalByValueComponent sono tutti compresi nello spazio dei nomi System.Data (DataColumn, DataSet, DataTable, DataView e DataViewManager).
Nota: |
---|
Le classi base degli oggetti il cui marshalling viene effettuato per valore e per riferimento sono rispettivamente Object e MarshalByRefObject, ma le corrispondenti classi derivate sono denominate MarshalByValueComponent e Component. La logica che ispira il criterio di denominazione assegna al tipo più usato il nome più semplice. |
Se un componente non verrà gestito da remoto, non lo si dovrà derivare dall'implementazione base di Component bensì direttamente da IComponent.
Per ulteriori informazioni sulla gestione remota di oggetti, vedere Cenni preliminari su .NET Remoting.
Controllo
Un controllo è un componente che fornisce capacità di interfaccia utente. .NET Framework fornisce due classi base per i controlli: una per i controlli Windows Form del lato client e l'altra per i controlli server ASP.NET. Queste classi sono System.Windows.Forms.Control e System.Web.UI.Control. Tutti i controlli della libreria di classi .NET Framework derivano, direttamente o indirettamente, da queste due classi. System.Windows.Forms.Control deriva da Component e fornisce funzionalità per l'interfaccia utente. System.Web.UI.Control implementa IComponent e fornisce l'infrastruttura per l'aggiunta delle funzioni d'interfaccia.
Nota: |
---|
Tutti i controlli sono componenti ma non è vero il contrario. |
Contenitore e sito
Se si stanno sviluppando componenti e controlli per Windows Form o per pagine Web Form (pagine ASP.NET), non occorre implementare contenitori o siti. Le finestre di progettazione di Windows Form e di Web Form sono contenitori di Windows Form e di controlli server ASP.NET. I contenitori forniscono servizi ai componenti e ai controlli da essi ospitati. In fase di progettazione, i controlli vengono collocati nella finestra di progettazione e ricevono da questa servizi. Per completezza, di seguito sono riportate le definizioni di contenitore e sito.
Container
Un contenitore è una classe che implementa l'interfaccia System.ComponentModel.IContainer o deriva da una classe che la implementa. Un contenitore contiene solitamente uno o più componenti denominati componenti figli del contenitore.Site
Un sito è una classe che implementa l'interfaccia System.ComponentModel.ISite o deriva da una classe che la implementa. I siti vengono forniti da un contenitore per la gestione e la comunicazione con i propri componenti figli. Contenitore e sito sono solitamente implementati insieme.
Vedere anche
Concetti
Cenni preliminari sulle proprietà
Attributi per componenti in fase di progettazione
Altre risorse
Sviluppo di controlli Windows Form personalizzati con .NET Framework