Interfacce e DataTable tipizzati

martedì 04 novembre 2008 - 15.11

Teech Profilo | Expert

Sono ancora alle prese con il mio DataTable tipizzato creato a mano e la classe che lo gestisce (per gestire dei Clienti ad esempio).
Per la comunicazione con il DB ho creato:
- Una classe che gestisce un DataAdapter (AdapterClienti)
- Una classe che crea un Datatable tipizzato e all'interno contiene una classe che gestisce i miei DataRow tipizzati (ClientiDB che contiene ClienteDB)
Per gestire i dati ho creato:
- Una classe collection che prende i dati dal mio DataTable tipizzato (Clienti)
- Una classe che gestisce ogni oggetto della collection (Cliente)
Per una più trasparente gestione dei dati e per maggiore astrazione ho intenzione di inserire delle interfacce per comunicare fra le varie classi.
Attualmente la mia classe ClienteDB implementa l'interfaccia ICliente e la classe Cliente accetta nel costruttore un oggetto di tipo ICliente. Tutto perfettamente funzionante.

Nella classe Clienti attualmente è la seguente:
Public Class Clienti Inherits CollectionBase Private _adapter As AdapterClienti Sub New() _adapter = New AdapterClienti Popola() End Sub Private Sub Popola() For Each cl As ICliente In _adapter.GetClienti Dim c As Cliente = New Cliente(CType(cl,ICliente)) Me.List.Add(c) Next End Sub End Class
Come potete notare istanzio l'oggetto _adapter di tipo AdapterClienti ma vorrei gestirlo con una Interfaccia. Ho creato un'interfaccia piuttosto semplice:
Public Interface IClienti Function GetClienti() As ICliente() End Interface
Per implementarla ho utilizzato il seguente modo:
Public Class AdapterClienti Implements IClienti ... Public Function GetClienti() As ClientiDB Implements IClienti.GetClienti ... End Function ... End Class
L'errore che mi viene restituito è il seguente:
"GetClienti" non può implementare "GetClienti" perché non esiste un function corrispondente nell'interfaccia "IClienti".
Ho capito (almeno credo) che il problema è che ClientiDB non è un array di ICliente (anche se ogni rows è in ICliente), ma non so da dove iniziare per correggere l'errore o comunque come risolverlo... Chi mi può mettere sulla direzione giusta?

Grazie!!!
--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole

freeteo Profilo | Guru

Ciao,
ti faccio qualche domanda "generale":
- Sei all'inizio del tuo progetto?
- Quante entita (che nel tuo caso sono tabelle nel dataset tipizzato) hai?
se la risposta è alla prima domanda è "si" oppure alla seconda è "<10" ti consiglio vivamente di cambiare approccio

Io non me ne intendo di dataset tipizzati perchè dopo pochi utilizzi li ho trovati subito una mezza porcheria...mischiara datatable con entità tirandosi dietro proprietà/metodi di oggetti non "puliti"
Il mio è un parere personale, ovvio che potrebbe essere idiozia in alcuni casi, ma sento di poterti suggerire di usare Linq2Sql se sei su sql oppure farti le tue Entità e poi popolarle tu a mano.
Sarà anche noioso all'inizio (per questo infatti va valutata la grandezza del progetto) ma se hai 1po di tempo da impiegare, cambia approccio e ne avrai altro che benefici.

Quello che ti consiglio io è questo:

- Progetto Entità => definisci tutte le tue proprietà, le classi base etc...e questo progetto lo referenzi in tutti gli altri, perchè è il tuo "domain-model", ad esempio per un oggetto "Ordine":
public class Ordine { public string Tipo { get; set; } public int Numero { get; set; } public string CodiceCliente { get; set; } .... }

- Progetto DataProvider => ti fai i tuoi metodi che generano collezioni (oppure singolo) degli oggetti, ad esempio IEnumerable<T> o List<T> etc... che ti servono, leggendo dal db, con un codice tipo:
public class OrdineDataProvider { public IList<Ordine> GetTutti() { List<Ordine> ordini = new List<Ordine>(); using (SqlConnection conn = new SqlConnection(...)) { SqlCommand cmd = conn.CreateCommand(); cmd.CommandText = "SELECT tipologia,numero,codiceCliente...FROM..."; conn.Open(); DbDataReader rd = cmd.ExecuteReader(); while (rd.Read()) ordini.Add(BuildOggetto(rd)); } return ordini; } protected Ordine BuildOggetto(IDataRecord rd) { Ordine ordine = new Ordine(); ordine.Tipo = Convert.ToString(rd["tipologia"]); ordine.Numero = Convert.ToInt32(rd["numero"]); ordine.CodiceCliente = Convert.ToString(rd["codiceCliente"]); .... return ordine; }

e via così, ti fai i vari metodi che ti servono con dei filtri etc...quello che ti serve insomma (ne fai uno per Entità).
Se poi hai linq2sql da poter usare, beh, diciamo che riduci veramente a poche righe il codice da scrivere in questo strato.


- Progetto Managers => (referenzia il dataprovider) una sorta di facciata "statica" che chiami quando ti serve e dentro li fai le validazioni, legami o altro che compone la tua logica di business, e poi chiama i metodi del dataprovider.
Anche qui dentro ne fai uno per Entità.
Questo strato potrebbe anche non servirti, se non hai grosse logiche da fare, ma è buona norma tenerlo anche se non ti serve immediatamente perchè in futuro potrebbe tornarti utile.

- Progetto Windows (o Web a seconda del progetto) => che usa i Manager per farsi dare gli oggetti che agganci in griglia tramite codice o ancora meglio, tramite Binding Source (finestra DataSource dove agganci le tue entità) e per riempirli poi usi i metodi del Manager.

Sono stato molto conciso nella spiegazione, perchè non so se hai la possibilità di cambiare approccio...il mio era un suggerimento poi se ti interessa/puoi, lo valutiamo nel dettaglio.

*ps: il codice è in C# perchè lo avevo comodo, ma puoi tradurlo facilmente in vb.net, tanto cmq devi scriverlo per la tua situazione.
ciao.

Matteo Raumer
[MVP Visual C#]
http://blogs.dotnethell.it/freeteo

Teech Profilo | Expert

Diciamo che nemmeno a me piacciono i DataSet tipizzati e proprio per questo mi sono creato a mano i miei DataTable tipizzati (che altro non sono che delle collection di DataRow per come li ho creati). Penso che come concetto quello che mi consigli è molto vicino a quello che stò realizzando (se ho capito bene):
- Entità: uso delle mie classi con relative proprietà e metodi per gestire i dati separatemente dal DB
- DataProvider: sono i miei Adapter che incapsulo in una classe per la gestione delle comunicazioni con il DB secondo le logiche che preferisco
- Managers: sono fondamentalmente le mie Collections dove gestisco le relazioni fra entità e le istanzio
- Progetto: faccio questo proprio per usare in modo corretto i BindingSource attraverso le classi.
Inoltre in questo modo riesco a tracciare in modo trasparente le modifiche (inserimento, modifiche e cancellazioni) di dati in modo diretto fra classi e DB (cambio un dato nella classe e con un solo metodo richiamo l'UpDate dell'Adapter che mi aggiorna il tutto con le logiche dei command da me creati).

Quello che non riesco a fare (e forse è il punto più a sfavore della mia "tecnica") è astrarre in modo completo i DataProvider dai Managers...
Usando il seguente metodo sul DataProvider sono riuscito a farmi restituire un elenco di "DataRow tipizzati" (che trasformo in classi) ed implementare l'interfaccia:
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra
Quando vado ad istanziare le classi ho trovato un piccolo problema... Questa è la classe collection:
Public Class Clienti Inherits CollectionBase Private _provider As IClienti Sub New() _provider = New IClienti <---PROBLEMA!!! Popola() End Sub Private Sub Popola() For Each cl As ICliente In _Provider.GetClienti Dim c As Cliente = New Cliente(CType(cl, ICliente)) Me.List.Add(c) Next End Sub End Class
Il problema, come si desume dal codice è che non riesco ad istanziare un DataProvider in quanto per me è un'interfaccia... Ma io non vorrei referenziare l'implementazione dell'interfaccia sul progetto altrimenti perdo tutta la "portabilità" e l'astrazione che cercavo.

P.S.: Non c'è problema per C# Grazie!!!
--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole

freeteo Profilo | Guru

>Diciamo che nemmeno a me piacciono i DataSet tipizzati e proprio
>per questo mi sono creato a mano i miei DataTable tipizzati (che
>altro non sono che delle collection di DataRow per come li ho
>creati).
Si le dataTable sono per definizione contenitori di DataRow, nel framework proprio è stato definito così (ma è anche ovvio mentalmente) e le DataRow sono contenitori di Celle.
Solo che non sarebbero "contenitori" puri, sono contenitori perchè espongono la loro proprietà "Item" su cui puoi iterare e accedere tramite indice o nome quando possibile.
Quello che dico è che hanno delle altre proprietà che nascono per coprire altre cose che potrebbero non servirti, non che siano "male" come oggetti anzi io li uso spesso, ma sicuramente non li uso per modellare, dove invece preferisco fare le cose "pulite" a mano (o con Linq se posso )


>vicino a quello che stò realizzando (se ho capito bene):
>- Entità: uso delle mie classi con relative proprietà e metodi
>per gestire i dati separatemente dal DB
queste vanno bene, però rimango dell'idea che meglio entità che non derivano da DataRow, meglio farle pulite con lo stretto necessario che ti serve, in modo da poterle riciclare il più possibile anche in futuro


>- DataProvider: sono i miei Adapter che incapsulo in una classe
>per la gestione delle comunicazioni con il DB secondo le logiche
>che preferisco
ok questo è proprio quello che serve, solo che anche qui, ti consiglio Linq2Sql se puoi e quindi usare un DataContext, oppure farti tu le associazioni delle proprietà come ti ho mostrato nel codice prima.


>- Managers: sono fondamentalmente le mie Collections dove gestisco
>le relazioni fra entità e le istanzio
ok


>- Progetto: faccio questo proprio per usare in modo corretto
>i BindingSource attraverso le classi.
ok. Come ti dicevo puoi usarlo anche agganciando che


>Inoltre in questo modo riesco a tracciare in modo trasparente
>le modifiche (inserimento, modifiche e cancellazioni) di dati
>in modo diretto fra classi e DB (cambio un dato nella classe
>e con un solo metodo richiamo l'UpDate dell'Adapter che mi aggiorna
>il tutto con le logiche dei command da me creati).
ok, è proprio questo l'obbiettivo, lavorare con oggetti e salvare quelli.Infatti lo strato DataProvider è un "data - provider" non un "SqlData..." o "OracleDAta..." è uno strato che gestisce la "persistenza" dei dati.
Se usi sql ok, ma domani potresti dover passare tramite un WebService, o un File Access, o un DataBase differernte come Mysql o Oracle, che hanno tipi magari diversi e gestiscono sintassi leggermente diverse.
In questi casi lo strato di DataProvider va cambiato con uno strato "Ad-hoc" per il db che faccia questo lavoro, ma al resto degli strati è trasparente...



>Quello che non riesco a fare (e forse è il punto più a sfavore
>della mia "tecnica") è astrarre in modo completo i DataProvider
>dai Managers...
qui ti basta usare il pattern "factory" (http://it.wikipedia.org/wiki/Abstract_factory) ossia avere una classe che ti "fabbrichi" l'oggetto reale che abbia quel comportamento (specificato nell'Interfaccia), in questo caso il tuo DataProvider da utilizzare.
L'interfaccia infatti non è una classe, ma definisce come si "presenta" una classe, ossia cosa può fare e come puoi interagire con lei, quindi ad esempio la classe "uomo" ha sicuramente "gambe" e "braccia" e può "correre" etc...ma non è detto che l'uomo sia "italiano", o "maschio" (meglio femmina direi io )
Quindi quello che fai è definire un'associazione tra il manager e qualcosa che a runtime verrà dato e che si comporterà in quel modo (tecnicamente implementerà quell'interfaccia).

Tutto questo discorso filosofico tradotto in codice diventa qualcosa tipo:
MANAGER:
-------------
internal class FactoryProvider { static IDataProviderFactory factory; static FactoryProvider() { string nome = "NomeAssembly"; Assembly assembly = Assembly.Load(nome); factory = (IDataProviderFactory)assembly.CreateInstance(nome + ".DataProviderFactory"); } internal static IArticoloDataProvider GetArticoloDataProvider() { return factory.GetAccountDataProvider(); } ....
notare il "CreateInstance" che crea l'oggetto in quel momento li, dall'assembly che hai caricato (NomeAssembly) che tipicamente ha tutto il namespace tipo "Progetto.Libreria"...lo capisci esplorando il file eventualmente con Reflector se proprio non lo sai subito.
Io ho usato metodi statici, vedi tu se vuoi farli in qualche altro modificatore...come vai meglio, è sostanzialmente lo stesso.


DATAPROVIDER:
-------------------
public class DataProviderFactory : IDataProviderFactory { public virtual IArticoloDataProvider GetArticoloDataProvider() { return new ArticoloDataProvider(); } ... tutti i metodi che servono a farti tornare le istanze reali dei vari DataProvider che mi serve .... }

e poi ogni provider che ti serve ad esempio:
public class ArticoloDataProvider : IArticoloDataProvider { ...

chiaramente l'interfaccia "IDataProviderFactory" (e anche IArticoloDataProvider) è stata referenziata in entrambi i progetti, io di solito faccio proprio un progetto a parte che contiene le farie interfacce...vedi tu se vuoi metterlo dentro al progetto Entità, dal mio punto di vista è sbagliato cmq il concetto è che sicuramente non devi referenziare lo strato "dataprovider" nei Manager, altrimenti sei sempre "legato" a quella libreria specifica...


>P.S.: Non c'è problema per C# Grazie!!!
ottimo , ti ho postato del codice veloce,giusto per introdurti alla strada migliore che conosco al momento.
Se non riesci ad applicare queste teorie al tuo progetto, magari girami via email un progetto fatto da te che provo a farlo io e poi ti dico come fare.

Grazie.
ciao.

Matteo Raumer
[MVP Visual C#]
http://blogs.dotnethell.it/freeteo

Teech Profilo | Expert

Veramente mille grazie!!!
Ho capito cosa intendi per non utilizzare DataRow ed è un concetto che mi piace molto e proverò ad implementare nei prossimi progetti in quanto anche a me piace avere il controllo completo di ciò che faccio... Usare oggetti "già fatti" è comodo ma non ti permette questo controllo completo ed in futuro potrebbe rivelarsi controproducente avere determinate caratteristiche sull'oggetto (che magari scopri solo quando non puoi più tornare indietro)... Chiarissimo!!!

Ora, quando posso mettermi con calma a guardarci, studierò il pattern Abstract Factory (per ora avevo conosciuto ed usato solo il Singleton, molto più semplice) ma questa prospettiva credo mi servirà moooolto in futuro. Non chiudo il thread in quanto potrei avere bisogno di disturbarti ulteriormente per l'applicazione del pattern che metterò in un progetto a parte insieme alle interfacce (che ho già in un progetto a parte).

Spero avrai pazienza di guardare se aggiorno il thread in quanto (al contrario di molti) mi piacerebbe riuscire da solo ad applicare il pattern per capirne esattamente il funzionamento e le potenzialità per applicazioni future; stò puntando molto la mia attività più sulla qualità dei prodotti a discapito della produttività ma è la mia mission per spianarmi la strada in futuro (spero sia la scelta giusta per diventare ricco che il mio scopo ultimo).

Due domande molto semplici:
1. Puoi consigliarmi un manuale (li uso molto nonostante internet) dove spiegano i pattern e le applicazioni degli stessi (mi rendo conto che sono utilissimi, ma senza conoscerne l'esistenza è difficile studiarli)
2. Ho per caso (inconsciamente) applicato la tecnica degli N-Tiers? (ovviamente con le giuste correzioni da apportare ad alcune logiche).

Per il momento veramente, ma veramente mille grazie!!!
--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole

freeteo Profilo | Guru

>questo controllo completo ed in futuro potrebbe rivelarsi controproducente
>avere determinate caratteristiche sull'oggetto (che magari scopri
>solo quando non puoi più tornare indietro)... Chiarissimo!!!
esatto, come dico sempre non è che ci sia "una sola strada" ma è meglio valutare la grandezza del progetto, e soprattutto cosa potrebbe essere ampliato in futuro, perchè se come spesso succede, devi fare delle aggiunte di funzionalità, meglio avere la strada asfaltata bene, che non dissestata piena di buche



>Ora, quando posso mettermi con calma a guardarci, studierò il
>pattern Abstract Factory (per ora avevo conosciuto ed usato solo
>il Singleton, molto più semplice) ma questa prospettiva credo
>mi servirà moooolto in futuro. Non chiudo il thread in quanto
>potrei avere bisogno di disturbarti ulteriormente per l'applicazione
>del pattern che metterò in un progetto a parte insieme alle interfacce
>(che ho già in un progetto a parte).
ok, architettare bene un'applicazione non è mica tanto semplice ed io non sono certo un maestro, ti consiglio solo qualcosa che ho potuto "verificare" sul campo essere un buon modus operandi che mi ha salvato le natiche in parecchie circostanze, sia di espansioni, ma anche di errori sistemati con il minor impatto nell'applicazione.



>Spero avrai pazienza di guardare se aggiorno il thread in quanto
>(al contrario di molti) mi piacerebbe riuscire da solo ad
>applicare il pattern per capirne esattamente il funzionamento
>e le potenzialità per applicazioni future; stò puntando molto
nessun problema, tanto mi arriva la mail di notifica



>la mia attività più sulla qualità dei prodotti a discapito della
>produttività ma è la mia mission per spianarmi la strada in futuro.
esatto, fai benissimo, se hai del margine per investire nello studio dell'architettura e lo sviluppo di un software, ti conviene perderci 1po di tempo, che ti tornerà sicuramente utile in futuro...


>(spero sia la scelta giusta per diventare ricco che il mio scopo
>ultimo)
ahahah devi cambiare lavoro se vuoi fare soldi...a fare il dev ne farai gran pochi secondo me, ma ti divertirai un sacco sicuramente e sfrutterai sempre il tuo cervello, che secondo me è veramente la cosa più importante che dobbiamo riempire, non le tasche



>Due domande molto semplici:
>1. Puoi consigliarmi un manuale (li uso molto nonostante internet)
>dove spiegano i pattern e le applicazioni degli stessi (mi rendo
>conto che sono utilissimi, ma senza conoscerne l'esistenza è
>difficile studiarli)
anche io preferisco i libri sinceramente, anche se purtroppo costano, vedi tu quanto spendere o dove recuperarli, io ti consiglio questi:
- http://www.martinfowler.com/books.html#eaa "la bibbia" dei pattern a mio avviso, sono trattati bene e sono generici.
- http://www.dofactory.com/Patterns/Patterns.aspx
- http://www.amazon.com/Applying-Domain-Driven-Design-Patterns-Examples/dp/0321268202/
- http://www.infoq.com/minibooks/domain-driven-design-quickly e anche altri della categoria "books" di questo libro sono interessanti e sopratutto sono free!
Come vedi spesso non si cita il linguaggio perchè i patterns sono teorie di programmazione "generiche" e quindi indipendenti dall'ambiente dove stai sviluppando Java o .Net etc.

poi ci sono anche altri contenuti interessanti da vedere:
- http://msdn.microsoft.com/it-it/cc296071.aspx
- http://en.wikipedia.org/wiki/Multitier_architecture
- http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?culture=en-US&EventID=1032269422&CountryCode=US
e poi altri di questo genere, io ti consiglio cmq di guardarti qualche webcast che ti aiuta anche a vedere realmente con visual studio aperto



>2. Ho per caso (inconsciamente) applicato la tecnica degli
>N-Tiers? (ovviamente con le giuste correzioni da apportare ad
>alcune logiche).
certo, la struttura a layers o cmq tiers (io non ho mai capito esattamente la differenza) è proprio questa, tipicamente 3-layers, ma a volte puoò aver senso anche 4...io sono fermo a 3 sinceramente
ciao.

Matteo Raumer
[MVP Visual C#]
http://blogs.dotnethell.it/freeteo

Teech Profilo | Expert

EDIT:
Ho capito di aver sbagliato buona parte del mio ragionamento... Ho cancellato tutto e ci riprovo...

--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole

Teech Profilo | Expert

Penso di esserci riuscito... Ti chiedo solo se secondo te ho fatto in modo corretto mettendo quello che ho fatto partendo dal principio.

Ho creato delle interfacce
Public Interface ICliente ReadOnly Property Codice() As String ReadOnly Property RagioneSociale() As String ReadOnly Property Indirizzo() As String ReadOnly Property PartitaIVA() As String '... ecc... End Interface Public Interface IClienti Function GetClienti() As List(Of MyCommon.ICliente) '...ecc... End Interface
Nel layer database ho creato un adapter che implementa le interfacce create (ok ho usato un Datatable tipizzato, lo ammetto, ma per ora sono già contento così) ed in particolare senza entrare nel merito del funzionamento ho implementato l'interfaccia IClienti come di seguito indicato:
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra
Ho quindi creato una classe Factory:
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra
A questo punto ho implementato le mie classi reali
Public Class Cliente Private _cliente As MyCommon.ICliente Public Sub New(ByVal cli As MyCommon.ICliente) _cliente = cli End Sub Public ReadOnly Property Codice() As String Get Return _cliente.Codice.ToString.Trim End Get End Property Public ReadOnly Property RagioneSociale() As String Get Return _cliente.RagioneSociale.ToString.Trim End Get End Property '... ecc... End Class Public Class Clienti Inherits CollectionBase Private _adapter As List(Of MyCommon.ICliente) Sub New() Try _adapter = (New MyCommon.MyFactoryClienti).GetClienti '<---QUI USO IL FACTORY Catch ex As Exception Throw ex End Try Popola() End Sub Private Sub Popola() For Each cl As MyCommon.ICliente In _adapter Me.List.Add(New Cliente(CType(cl, MyCommon.ICliente))) Next End Sub '... ecc... End Class
In ultimo, per completezza, uso le classi reali per visualizzare/elaborare i dati sulla form
Public Class MyForm Dim bs As BindingSource Private Sub MyForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Try Dim cc As Clienti = New Clienti bs = New BindingSource bs.DataSource = cc Catch ex As Exception MessageBox.Show(ex.Message) End Try dgv.DataSource = bs End Sub '... ecc... End Class
Credo, in questo modo, di aver dato il massimo grado di astrazione possibile fra il Data Access Layer e il Business Object Layer utilizzando il pattern Abstract Factory.

Ora le immancabili domande:
- Ha senso creare un'interfaccia per la classe factory? Non nego di averci provato e non esserci riuscito, ma poi ho abbandonato perchè non credo sia fondamentale
- Usando la Reflection (ho iniziato a studiarla in questi giorni per risolvere questa cosa) come posso sapere quale Classe devo istanziare se nel mio assembly se ce ne sono più di una (ora uso una costante)? Sarebbe correto sapere quale classe implementa l'interfaccia (sempre che solo una la implementi). Come è possibile rendere più dinamico questo passaggio.
- E' correto creare un singolo Factory per tutti i tipi di oggetto o è meglio creare un factory per ogni tipo di oggetto (Avrò anche gli oggetti Articoli, Operatori, ecc...). Direi di no, però andrei a "complicare" il codice ed avendo i factory nel "Framework" della mia applicazione potrebbe quasi essere fattibile.

Scusami tanto se ne approfitto ma ho capito più nelle ultime 48 ore che negli ultimi 48 giorni... (P.S.: ho già provveduto ad acquistare manuali sui Pattern e su LINQ e stò provando a capire la Reflection).

Ciao!!!
--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole

freeteo Profilo | Guru


>Dim assembly As Reflection.Assembly = Reflection.Assembly.LoadFrom(MyCommon.MyRegistry.AssemblyClienti)
>'<--- Uso una classe per indicare quale assembly usare per
>ora
>_factory = CType(assembly.CreateInstance("Database.AdapterClienti"),
>MyCommon.IClienti)
> Catch ex As Exception
qui non capisco, carichi l'assembly per la factory ogni volta? verifica le prestazioni.
Io cmq uso un assembly solo, caricato una volta, che mi fa da "Factory" ossia "fabbrica" le varie istanze dei vari Provider (Adapters nel tuo caso), ma come vedi dal codice precedente, viene fatto una sola volta.




>Credo, in questo modo, di aver dato il massimo grado di astrazione
>possibile fra il Data Access Layer e il Business Object Layer
>utilizzando il pattern Abstract Factory.
si direi abbastanza corretto, rimane quel mio dubbio sul fatto che io solitamente ho solo una factory, e non una per provider, questa factory (che ha la sua interfaccia appunto) crea le istanze che sono poi le classi che hai scritto nel progetto dei providers, infatti questa è scritta nel provider stesso (dato che è l'unico che può darti l'istanza dato che fisicamente il codice compilato è la dentro )


>Ora le immancabili domande:
>- Ha senso creare un'interfaccia per la classe factory? Non nego
>di averci provato e non esserci riuscito, ma poi ho abbandonato
>perchè non credo sia fondamentale
secondo me si, se non riesci ti preparo un progettino d'esempio per spiegarti cosa intendo


>- Usando la Reflection (ho iniziato a studiarla in questi giorni
>per risolvere questa cosa) come posso sapere quale Classe devo
>istanziare se nel mio assembly se ce ne sono più di una (ora
>uso una costante)? Sarebbe correto sapere quale classe implementa
>l'interfaccia (sempre che solo una la implementi). Come è possibile
>rendere più dinamico questo passaggio.
si diciamo che per comodità (ed evitare di fare il discovery che porta via CPU) so già a priori cosa chiamare, infatti la factory ha un metodo "GetClienteDataProvider" il quale torna un oggetto che implementa l'interfaccia "IClienteDataProvider".
Poi che dentro all'assembly ci sia una classe che si chiama "pippo" o "pluto" non importa il nome, l'importante è che implementi quella sua interfaccia "IClienteDataPRovider" che appunto è quello che ti torna la factory.



>- E' correto creare un singolo Factory per tutti i tipi di oggetto
>o è meglio creare un factory per ogni tipo di oggetto (Avrò anche
>gli oggetti Articoli, Operatori, ecc...). Direi di no, però andrei
>a "complicare" il codice ed avendo i factory nel "Framework"
>della mia applicazione potrebbe quasi essere fattibile.
quindi da quello che ti ho detto sopra, io lo preferisco come cosa, ma non è assolutamente necessario



>Scusami tanto se ne approfitto ma ho capito più nelle ultime
>48 ore che negli ultimi 48 giorni... (P.S.: ho già provveduto
>ad acquistare manuali sui Pattern e su LINQ e stò provando
>a capire la Reflection).
ottimo!
ciao.

Matteo Raumer
[MVP Visual C#]
http://blogs.dotnethell.it/freeteo

Teech Profilo | Expert

Mi sono cadute delle certezze: AIUTO!!! Dimmi se ho capito bene.
Il factory è una classe per istanziare delle classi "sconosciute" alla classe che le utilizzerà. In una situazione "normale" avendo una classe MiaClasse, ogni volta che la istanzio faccio un Dim var as New MiaClasse. Come ho fatto io non è lo stesso discorso?
In ogni modo è più che corretto dare un occhio alle prestazioni. Se il mio factory lo correggo così:
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra
Avendo un Campo Privato Statico (_factory) e istanziandolo solo se è Nothing, correggo il problema? O quello che mi volevi far notare è altro?

Per le interfacce e per il discorso del Factory unico devo ragionarci un po'
Grazie Mille!!!

P.S.: Porta ancora un po' di pazienza e scusami tanto, sento di esserci vicino...
--------------
Maurizio Brini
--------------
Nessuna impresa è mai stata compiuta da un uomo ragionevole
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5