Il pattern visitor è un meccanismo per simulare il doppio binding nei linguaggi di programmazione che supporta solo il binding singolo. Sfortunatamente, questa affermazione potrebbe non chiarire molto le cose, quindi lasciatemi spiegare con un semplice esempio.
In .NET e C #, la piattaforma che stai utilizzando, gli oggetti possono essere convertiti in stringhe usando la funzione ToString()
. Ciò che questa funzione, ovvero il codice che viene eseguito, dipende dal tipo di oggetto a cui lo stai applicando (è un metodo virtuale). Il codice che viene eseguito dipende da una cosa, l'unico tipo di oggetto, quindi il meccanismo utilizzato è chiamato binding singolo.
Ma cosa succede se voglio avere più di un modo per convertire un oggetto in una stringa, per ogni diverso tipo di oggetto? Cosa succede se volevo avere due modi per convertire gli oggetti in stringhe, in modo che il codice da eseguire dipenda da due cose: non solo l'oggetto da convertire, ma anche il modo in cui vogliamo convertirlo?
Potrebbe essere risolto bene se avessimo un doppio legame. Ma la maggior parte dei linguaggi OO, incluso C #, supporta solo l'associazione singola.
Il pattern visitor risolve il problema, trasformando il dual binding in due singoli binding succesivi.
Nel nostro esempio precedente, userebbe un metodo virtuale nell'oggetto da convertire, che chiama un secondo metodo virtuale nell'oggetto che implementa l'algoritmo di conversione.
Ma ciò implica che l'oggetto su cui si desidera applicare l'algoritmo deve collaborare con questo: ha bisogno di supporto per il pattern del visitatore cotto in.
Sembra che tu stia utilizzando le classi di Windows Form di .NET, che non hanno il supporto per il pattern del visitatore. Più precisamente, avrebbero bisogno di avere un metodo public virtual void Accept(IVisitor)
, che ovviamente non hanno.
Quindi, qual è l'alternativa? Bene, .NET non supporta solo il binding singolo, ma supporta anche il binding dinamico, che è ancora più potente del dual binding.
Per ulteriori informazioni su come applicare quella tecnica, che ti permetterà di risolvere il tuo problema (se lo capisco bene), dai un'occhiata a Visitatori di addio .
UPDATE:
Per applicare la tecnica al tuo problema specifico, devi prima definire il tuo metodo di estensione:
public static XmlDocument ToXml(this Control control)
{
XmlDocument xml = new XmlDocument();
XmlElement root = xml.CreateElement(control.GetType().Name);
xml.AppendChild(root);
Visit(control, xml, root);
return xml;
}
Crea il dispatcher dinamico:
private static void Visit(Control control, XmlDocument xml, XmlElement root)
{
dynamic dynamicControl = control; //notice the 'dynamic' type.
//this is the key to dynamic dispatch
VisitCore(dynamicControl, xml, root);
}
Quindi inserisci i metodi specifici:
private static void VisitCore(Control control, XmlDocument xml, XmlElement root)
{
// TODO: specific Control handling
}
private static void VisitCore(ContainerControl control, XmlDocument xml, XmlElement root)
{
// call the "base" method
VisitCore(control as Control, xml, root);
// TODO: specific ContainerControl handling
// for example:
foreach (Control child in control.Controls)
{
XmlElement element = xml.CreateElement(child.GetType().Name);
root.AppendChild(element);
// call the dynamic dispatcher method
Visit(child, xml, element);
}
}
private static void VisitCore(Form control, XmlDocument xml, XmlElement root)
{
// call the "base" method
VisitCore(control as ContainerControl, xml, root);
// TODO: specific Form handling
}