A vegades fent un webservice m'he trobat amb la necessitat d'enviar objectes, o en interfaces JSON fer objectes per enviar-los. En ambdós casos és necessari convertir un DataRow a un objecte. O un DataTable a una llista d'objectes.
Com sempre he afegit a la clsDades les funcions pertinents. El primer que cal entendre és la reflection que és obtenir informació d'objectes (propietats, tipus de dades, longituds) en temps d'execució i actuar en conseqüència.
La primera funció que converteix una taula a una llista d'objectes és molt restrictiva, ja que els noms de les columnes dels registres han de coincidir amb el nom de les propietats del objecte. També el tipus ha de coincidir, encara que el més recomanable és que ambdós siguin cadenes de text (strings).
public List<T> ToList<T>(DataTable tbl) where T : new()
{
List<T> theList = new List<T>();
T item;
List<PropertyInfo> properties = typeof(T).GetProperties().ToList();
foreach (DataRow DR in tbl.Rows)
{
item = CrearItem<T>(DR, properties);
theList.Add(item);
}
return theList;
}
public T CrearItem<T>(DataRow row, List<PropertyInfo> properties) where T : new()
{
T item = new T();
foreach (PropertyInfo property in properties)
{
property.SetValue(item, row[property.Name], null);
}
return item;
}
Aquesta funció és molt limitada, llavors he fet una altra que inclou els Mappings. Es a dir que les columnes de la taula poden tenir un nom diferent del de les propietats de l'objecte que es crea. Aprofitant la informació que es dels camps es pot fer una conversió de tipus, sempre i quan siguin tipus compatibles el de la columna i el de la propietat de l'objecte. El codi canvia força:
public List<T> ToList<T>(DataTable tbl, Dictionary<string, string> Mappings) where T : new()
{
List<T> theList = new List<T>();
T item;
List<PropertyInfo> properties = typeof(T).GetProperties().ToList();
foreach (DataRow DR in tbl.Rows)
{
item = CrearItem<T>(DR, properties, Mappings, true);
theList.Add(item);
}
return theList;
}
public T CrearItem<T>(DataRow DR, List<PropertyInfo> properties,
Dictionary<string, string> Mappings, bool UseCampInfo) where T : new()
{
T item = new T();
DateTime ValorData;
Decimal ValorDecimal;
clsCamp Camp;
foreach (PropertyInfo property in properties)
{
if (Mappings.ContainsKey(property.Name))
{
Camp = BuscaCamp(Mappings[property.Name]);
if (Camp == null)
{
throw new Exception("Camp " + Mappings[property.Name] + " no trobat");
}
else
{
if (!DR.IsNull(Camp.NomCamp))
{
switch (Camp.Tipus)
{
case Tipus.date:
if (property.PropertyType == Type.GetType("System.String"))
{
ValorData = (DateTime)DR[Camp.NomCamp];
if (string.IsNullOrEmpty(Camp.Format)) property.SetValue(item,
ValorData.ToShortDateString(), null);
else property.SetValue(item, ValorData.ToString(Camp.Format), null);
}
else
{
property.SetValue(item, DR[Camp.NomCamp], null);
}
break;
case Tipus.datetime:
if (property.PropertyType == Type.GetType("System.String"))
{
ValorData = (DateTime)DR[Camp.NomCamp];
if (string.IsNullOrEmpty(Camp.Format)) property.SetValue(item,
ValorData.ToString("dd/MM/yyyy HH:mm"), null);
else property.SetValue(item, ValorData.ToString(Camp.Format), null);
}
else
{
property.SetValue(item, DR[Camp.NomCamp], null);
}
break;
case Tipus.time:
if (property.PropertyType == Type.GetType("System.String"))
{
ValorData = (DateTime)DR[Camp.NomCamp];
if (string.IsNullOrEmpty(Camp.Format)) property.SetValue(item,
ValorData.ToString("HH:mm"), null);
else property.SetValue(item, ValorData.ToString(Camp.Format), null);
}
else
{
property.SetValue(item, DR[Camp.NomCamp], null);
}
break;
case Tipus.dec:
if (property.PropertyType == Type.GetType("System.String"))
{
ValorDecimal = (Decimal)DR[Camp.NomCamp];
if (string.IsNullOrEmpty(Camp.Format)) property.SetValue(item,
ValorDecimal.ToString(), null);
else property.SetValue(item, ValorDecimal.ToString(Camp.Format), null);
}
else
{
property.SetValue(item, DR[Camp.NomCamp], null);
}
break;
default:
if (property.PropertyType == Type.GetType("System.String"))
property.SetValue(item, DR[Camp.NomCamp].ToString(), null);
else property.SetValue(item, DR[Camp.NomCamp], null);
break;
}
}
}
}
}
return item;
}
private clsCamp BuscaCamp(string pCamp)
{
for (int i = 0; i < CampsResultat.Length; i++)
{
if (CampsResultat[i].NomCamp == pCamp)
{
return CampsResultat[i];
}
}
return null;
}
|