Le modèle de visiteur est un mécanisme permettant de simuler une double liaison dans des langages de programmation qui ne prennent en charge qu'une seule liaison. Malheureusement, cette déclaration peut ne pas clarifier beaucoup les choses, alors laissez-moi vous expliquer avec un exemple simple.
Dans .NET et C #, la plateforme que vous utilisez, les objets peuvent être convertis en chaînes à l'aide de la ToString()
fonction. Ce que fait cette fonction, c'est-à-dire le code en cours d'exécution, dépend du type d'objet auquel vous l'appliquez (c'est une méthode virtuelle). Le code exécuté dépend d'une chose, du type d'objet, c'est pourquoi le mécanisme utilisé est appelé liaison simple.
Mais que se passe-t-il si je veux avoir plus d'une façon de convertir un objet en chaîne, pour chaque type d'objet différent? Et si je voulais avoir deux façons de convertir des objets en chaînes, de sorte que le code en cours d'exécution dépend de deux choses: non seulement l'objet à convertir, mais aussi la manière dont nous voulons qu'il soit converti?
Cela pourrait être bien résolu si nous avions une double liaison. Mais la plupart des langages OO, y compris C #, ne prennent en charge que la liaison unique.
Le modèle de visiteur résout le problème en transformant la double liaison en deux liaisons simples successives.
Dans notre exemple ci-dessus, il utiliserait une méthode virtuelle dans l'objet à convertir, qui appelle une deuxième méthode virtuelle dans l'objet implémentant l'algorithme de conversion.
Mais cela implique que l'objet sur lequel vous souhaitez appliquer l'algorithme doit collaborer avec cela: il doit prendre en charge le modèle de visiteur intégré.
Vous semblez utiliser les classes Windows Forms de .NET, qui ne prennent pas en charge le modèle de visiteur. Plus précisément, ils auraient besoin d'une public virtual void Accept(IVisitor)
méthode, ce qu'ils n'ont évidemment pas.
Alors, quelle est l'alternative? Eh bien, .NET ne prend pas seulement en charge la liaison simple, il prend également en charge la liaison dynamique, ce qui est encore plus puissant que la double liaison.
Pour plus d'informations sur la façon d'appliquer cette technique, qui vous permettra de résoudre votre problème (si je le comprends bien), jetez un œil à Farewell Visitor .
MISE À JOUR:
Pour appliquer la technique à votre problème spécifique, définissez d'abord votre méthode d'extension:
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;
}
Créez le répartiteur dynamique:
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);
}
Remplissez ensuite les méthodes spécifiques:
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
}