Newsgroup: it.comp.dotnet
Titolo: Estendibilità di un visitor pattern

Ciao a tutti,
ecco la mia gerarchia di classi:
interface IVisitor<T>
{
	T Visit(Foo item);
	T Visit(Bar item);
}
interface IVisitable
{
	T Accept<T>(IVisitor<T> visitor);
}
class Foo : IVisitable { ... }
class Bar : IVisitable { ... }
ora, in un altro assembly ho la necessità di definire una nuova classe 
che implementa IVisitable e *due* implementazioni di IVisitor<T>
class AVisitor : IVisitor<int>
{
	int Visit(Foo foo) { ... }
	int Visit(Bar bar) { ... }
	int Visit(Widget w) { ... } //aggiunto
}
class AVisitor : IVisitor<string> : IVisitor<string> { ... } //come sopra
class Widget : IVisitable { ... }
Come faccio a estendere l'interfaccia di IVisitor<T>?
Grazie,
Giulio
-- 

 Come faccio a estendere l'interfaccia di IVisitor<T>?
Un metodo potrebbe essere:
public static class Extensions
{
	public static int Visit(this AVisitor v, Widget w) { ... }
         public static string Visit(this BVisitor v, Widget g) { ... }
         public static T Visit<T>(this IVisitor<T> me, Gadget g)
         {
             if (me is AVisitor)
             {
                 int a = ((AVisitor)me).Visit(g);
                 return (T)(object)a;
             }
             if (me is BVisitor)
             {
                 string b = ((BVisitor)me).Visit(g);
                 return (T)(object)b;
             }
             throw new ArgumentException();
         }
}
Il problema è quel dannatissimo type-checking sul visitor con 
conseguente numero infinito di cast. :-( Tuttavia, considerando che 
l'alternativa è fare type-checking sulle mie entità (che implementano 
IVisitable) e che le entità sono meno dei visitor, forse è meglio che mi 
accontento di questi quattro guai. :-) Qualche consiglio?
Ciao,
Giulio
-- 

 Come faccio a estendere l'interfaccia di IVisitor<T>?
perchè non un IVisitor<T, K>?
interface IVisitor<T, K>
{
    T Visit(K item);
}
interface IVisitable
{
    T Accept<T>(IVisitor<T, K> visitor);
}
.m
-- 
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCTS
http://mvp.support.microsoft.com
blog @ 
http://milestone.topics.it
whynot [ at ] topics [ dot ] it

 }
Uhm... due osservazioni a seguito del Cut&Paste -> Compila -> scrivi un 
paio di classi -> F5.
1. nella dichiarazione del metodo Accept di IVisitable manca un tipo 
generico K, evidentemente ti è sfuggita.
2. onestamente non riesco proprio a figurarmi *nessun* esempio di 
utilizzo. Potresti darmi qualche indicazione in più?
Grazie,
Giulio
-- 

 onestamente non riesco proprio a figurarmi *nessun* esempio di utilizzo. 
neanche io, era solo un'elucubrazione fatta in treno.



Sempre se sto capendo, un'idea per il secondo assembly sarebbe
estendere le interfacce e lavorare con un pattern esteso a tutti gli
effetti:
-------------
interface IVisitor2<T> : IVisitor<T>
{
        T Visit(Widget item);
}
interface IVisitable2 : IVisitable
{
        T Accept<T>(IVisitor2<T> visitor);
}
class AVisitor : IVisitor2<int>
{
        int Visit(Foo item) { ... }
        int Visit(Bar item) { ... }
        int Visit(Widget item) { ... }
}
class BVisitor : IVisitor2<string> { ... }
class Widget : IVisitable2 { ... }
-------------
Scritto dal divano... :)
-LV


Fors IVisitable2 non deve estendere IVisitable, ma a questo punto
avrei bisogno di aprire VS...
-LV
