Newsgroup: it.comp.lang.visual-basic
Titolo: List (Of Interfaccia)

Ciao a tutti,
ho due classi (e due tabelle) che per ora hanno sostanzialmente le stesse
proprietà e metodi, per cui in un'interfaccia ho messo le proprietà in
comune.
Ho un metodo che mi deve caricare i dati da queste due tabelle e metterli
insieme in un elenco di quest'interfaccia.
        Dim lst As New List(Of IEvento)
                For Each row As DataRow In dt.Rows
***                 Dim eve As New IEvento
                    With eve
                        .Id = Convert.ToInt64(row("ID"))
                        .Note = row("NOTE").ToString
                    End With
                    lst.Add(eve)
                Next
Ovviamente non mi compila la riga *** perchè non posso fare il New di
un'interfaccia.
Ho sbagliato approccio, o come posso fare un metodo che mi restituisca un
elenco di quest'interfaccia?
Sarebbe stato il caso di fare due classi derivate invece di un'interfaccia?
Le due classi adesso sono uguali apparte una proprietà in più e il metodo
di salvataggio diverso, ma logicamente potrebbero poi differire col tempo.
Tnx

 di salvataggio diverso, ma logicamente potrebbero poi differire col tempo.
l'approccio è giustissimo e avresti lo stesso risultato (e lo stesso 
problema) se usassi delle classi derivate.
L'inghippo con cui ti sei scontrato è una cosa che si chiama 
"idratazione", nel tuo ciclo for devi per forza mettere una serie di 
"if" che sulla base di qualche cosa determinano se creare la classe "A" 
o la classe "B" (entrambe che ereditano dall'interfaccia comune).
Considerazione personale: è ora che scopri che cosa è un ORM (tipo 
NHibernate) perchè queste cose le avresti tutte gratis.
Inoltre mi pare di capire che cominci ad affrontare problematiche che 
vanno un filino oltre il mero caricamento dei dati, rischi di investire 
molto più tempo sulla strategia e sulle problematiche di caricamento 
piuttosto che sull'applicazione vera e propria.
.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

 piuttosto che sull'applicazione vera e propria.
Hai pienamente ragione, ma ho scadenze di sviluppo settimanali e già ora è
complicato rispettarle. Inoltre questo è il primo progetto .NET che va
oltre le 2 form, per cui lo scalino sarebbe un po' troppo alto.
Tralasciamo poi che dall'inizio è cambiato radicalmente il sw a livello di
logica...

 problema) se usassi delle classi derivate.
.....
Cosi' a naso...
a meno che la classe base non fosse istanziabile, quindi (se ho ben capito 
il problema), potrebbe istanziare tanti oggetti base all'interno del ciclo, 
utilizzarli per il loro scopo e poi buttarli.
Chissa' se mi sono spiegato (e se ho ben capito il problema)
Ciao.. Maurizio 

 Chissa' se mi sono spiegato (e se ho ben capito il problema)
Allora non c'č una classe base, ma ci sono due classi simili che
condividono un'interfaccia.
Io devo restituire un elenco di "interfaccia", mi interessano i dati in
comune. Devo per forza dichiarare un oggetto (a caso) che implementa quella
interfaccia per poterlo aggiungere all'elenco?
Ripeto che comunque adesso ho una classe minima che implementa
l'interfaccia piů altre cose che mi servono, quindi il problema č risolto,
nel senso che ora non restituisco piů un Ienumerable (Of INTERFACCIA) ma
IEnuberable(Of ClasseMinima).

 IEnuberable(Of ClasseMinima).
...
Avresti potuto (anzi, forse e' meglio, se ho capito quello che ti serve) 
restituire comunque una Ienumerable (Of Interfaccia), dove la tua lista e' 
la lista di oggetti di tipo (ClasseMinima)

 adesso, anche per necessità solte dopo.
ma non ha molto senso fatta così, dalla domanda iniziale io deduco che 
tu sei in una condizione di questo tipo:
Animal
  Dog
  Cat
  Bird
e vuoi avere una List(Of Animal) in cui però dentro ci siano 
effettivamente istanze di Dog, Cat etc in base a quello che 
effettivamente sono.


 la lista di oggetti di tipo (ClasseMinima)
Si in effetti poi ho riguardato ed ho fatto proprio cosě, mi pareva di aver
cambiato anche il tipo restituito invece no.

 effettivamente sono.
L'esempio reale č che ho due tabelle "prescrizioni", "somministrazioni",
sono sostanzialmente identiche apparte per qualche campo (per ora). Ho
deciso di tenerle separate perchč la somministrazione ha l'id della
prescrizione eventuale.
Ho una funzione che mi deve restituire un elenco di record
indipendentemente che siano di uno o dell'altra tabella (in pratica
derivano da una SELECT UNION)
Dopo aver posto la domanda perņ poi mi serviva anche sapere se un record č
di un tipo o di un altro, quindi all'Interfaccia ho aggiunto un campo Enum
Tipo=Prescrizione, Somministrazione.
Le classi Prescrizione e Somministrazione hanno quella property
precompilata:
Property Tipo As EventoRecord = EventoRecord.Prescrizione Implements
IEvento.Tipo
La classe "minima" che poi ho fatto, ha quella proprietą che viene popolata
dalla funzione che recupera i dati.

 dalla funzione che recupera i dati.
se funziona non vedo problemi, ma architetturalmente è la scelta 
sbagliata, la scielta corretta sarebbe quella dell'esempio che ti ho 
fatto.


 fatto.
Il fatto è che a me serviva il sottoinsieme di prorietà "comuni" (presenti
nell'interfaccia) non il resto.
Tnx

 nell'interfaccia) non il resto.
non ho capito se la soluzione che hai trovato ti aggrada o meno


 non ho capito se la soluzione che hai trovato ti aggrada o meno
Mi funziona e mi basta, mi domandavo però in linea teorica se ho classi che
condividono un interfaccia, e mi serve sapere soli i dati dell'interfaccia
(ok raramente interfaccie si usano per raggruppare proprietà), se c'era una
strada migliore.
Comunque mi va bene quel che ho fatto :)

 strada migliore.
...
Da quel che ho imparato...
Se si tratta di oggetti che hanno una base comune, usi una classe base e poi 
derivi (il classico esempio Mammiferi- Cani, Gatti ecc..)
Se si tratta di oggetti che tra loro non hanno nulla in comune se non alcune 
proprieta' o metodi, interfaccia (ad esempio Automobile e Cavallo, hanno in 
comune Colore, Velocita' Max ecc. ma sono cose completamente diverse).
Di solito mi comporto cosi'.

 strada migliore.
Entrambe le soluzioni sono valida ma hanno tipicamenete (ripeto 
tipicamente) scopi diversi, riprendo il mio esempio di prima per stare 
bassi di profilo:
Animal
  Dog
  Cat
  Bird
diciamo che Animal ha il metodo Foo() e ogni animale implementa a modo 
sua Foo, e poi hai questo;
Zoo
  List<Animal> Animals
Hai una gerarchia di classi diciamo che puoi avere due obiettivi:
a) hai bisogno di avere la lista degli animali, iterare aulla lista, e 
invocare il metodo Foo e naturalmente ti aspetti che venga 
correttamente invocato (polimorfismo) il metodo Foo implementato da 
ogni singolo tipo
b) hai bisogno di avere una lista di animali e vuoi le proprietà comuni 
e lo scopo è banalmente produrre un report, quindi ti interessa 
relativamente che sia un Dog o un Cat basta che tu sappia il nome, il 
colore, e quello che più ti aggrada.
Il primo caso è una mezza rogna da risolvere a mano, un ORM qui fa 
faville e ti sbologan un sacco di magange, perchè devi tipicamente fare 
una query in cui aggreghi tutti i dati, poi iteri sul recordset e in 
base ad un campo discriminante decidi se istanziare un Dog o un Bird, 
etc...
il secondo caso invece ricade sotto il nome di "Projection", hai quindi 
una quarta entità (e.g. AnimalReport) che espone le sole proprietà che 
ti interessano, esegui una query che aggrega i risultati e carica le 
sole cose che ti servono e idrati AnimalReport.
Ovviamente fanno due cose abissalmente diverse, entrambe utili in 
contesti ben specifici.


 Di solito mi comporto cosi'.
Nel mio caso sono due tabelle speculari, una le prescrizioni e una le
somministrazioni del farmaco. Per ora sono molto simoli, però a logica sono
diversi, in effetti la classe base potrebbe essere un "EventoMedico" ma
sarebbe comunque MustInherit ad occhio.

 colore, e quello che più ti aggrada.
Manco a dirlo è un po' un miscuglio.
Sarebbe la B), salvo poi in corso d'opera è stato necessario sapere anche
che animale è.
Per ora, bruttamente, nell'interfaccia ho messo un campo "Tipo" di Enum e
valorizzo fisso nelle classi che la implementano.
Comunque il problema è risolto, e dato che è possibile che venga stravolto,
mi accontento che vada :)