Quando usiamo le classi tipizzate per rappresentare le nostre entità di Business spesso mappiamo queste classi con le tabelle presenti nel nostro Database.
Esempio una tabella utente simile a questa:
La rappresentiamo come entità in questo modo
#region fields
private Int32 _idUtente;
private string _cognome;
private string _nome;
private DateTime _dataNascita;
private string _indirizzo;
private string _posizione;
#endregion
#region properties
public Int32 IdUtente
{
get { return _idUtente; }
set { _idUtente = value; }
}
public string Cognome
{
get { return _cognome; }
set { _cognome = value; }
}
public string Nome
{
get { return _nome; }
set { _nome = value; }
}
public DateTime DataNascita
{
get { return _dataNascita; }
set { _dataNascita = value; }
}
public string Indirizzo
{
get { return _indirizzo; }
set { _indirizzo = value; }
}
public string Posizione
{
get { return _posizione; }
set { _posizione = value; }
}
#endregion
Per caricare questa entità usiamo un
DataReader sia per recuperare il singolo record che una lista.
Per caricare tutte le proprietà dellentità (la nostra classe tipizzata) di solito dobbiamo richiamare tutti i nomi dei campi che mappano la nostra entità. Capite bene che se sono parecchi campi diventa un po noioso ma indispensabile anche perché bisogna effettuare il giusto casting.
Esempio:
if(reader["Cognome"] != DBNull.Value)
{
this.Cognome = reader["Cognome"].ToString();
}
O ancora meglio usando i metodi
DataReader.GetOrdinal e i singoli
Get in base al tipo restituito.
Se invece non vogliamo scrivere una istruzione per ogni campo possiamo utilizzare la
Reflection in questo modo:
ci definiamo una classe
Utils così che può essere richiamata da tutte le nostre entità e poi creiamo un metodo statico
SetFields:
using System.Data.SqlClient;
using System.Reflection;
public class Utils
{
public static object SetFields(object item, SqlDataReader reader)
{
PropertyInfo[] listProperty;
Type _type = item.GetType();
listProperty = _type.GetProperties();
foreach (PropertyInfo singleProperty in listProperty)
{
singleProperty.SetValue(item, reader[singleProperty.Name], null);
}
return item;
}
}//endclass
Analizziamo il codice:
Come parametri passiamo un
object item che sarà la nostra classe e un
DataReader che in questo esempio usa il provider SQL ma può essere anche un altro senza problemi.
Definiamo un' array di Proprietà con l'istruzione:
PropertyInfo[] listProperty;poi come abbiamo visto in altri articoli sulla
Reflection dobbiamo impostare il
Type sul quale lavorare e nel nostro caso sarà:
Type _type = item.GetType();Poi recuperiamo tutte le proprietà dell'oggetto:
listProperty = _type.GetProperties();Poi eseguiamo un ciclo sull'array e settiamo la proprietà con il metodo
SetValue:
foreach (PropertyInfo singleProperty in listProperty
{
singleProperty.SetValue(item, reader[singleProperty.Name], null);
}
Come vedete con la proprietà
Name andiamo a recupera esattamente il campo e quindi cè un mapping 1 a 1 tra campo e proprietà e in automatico viene fatto il casting alloggetto recuperato.
Infine nella nostra classe utente creiamo per esempio un metodo
Get così fatto
public Utente Get()
{
//Recupero il DataReader dal mio layer DAL
using(SqlDataReader reader = Dal.GetDataReader("GetUtente"))
{
while(reader.Read())
{
Utente _utente = Utils.SetFields(this, reader);
return _utente;
}
}
}
Quindi come potete vedere con un solo metodo e poche righe di codice possiamo aumentare di molto la produttività delle nostre classi tipizzate.