En otro post puse un ejemplo de reflexión.
Ahora vamos a ver otro uso de la reflexión, en este caso para convertir un dataReader en un lista genérica, es decir en un tipo IEnumerable<T>
El escenario es útil en los siguientes casos:
- Trabajamos con LINQ y nos hemos acostumbrado a utilizarlo para tratar las entidades de negocio.
- Si trabajamos con un ORM (Entity, NHibernate) enlazaremos fácilmente las entidades de negocio y consultas con listas.
- Pero, si, no trabajamos con un ORM, no lo tendremos tan cómodo.
- Tampoco si trabajamos con un ORM con enfoque Code First y obtenemos los datos de un procedimiento almacenado.
- Independientemente de la utilidad del método, queremos ver un ejemplo de método de extensión y/o reflexión.
Paso 1. Crear Método de reflexión.
Recibe por parámetro:
Un Objeto al que copiar el valor de la propiedad. Observar que es un paso por referencia.
El nombre/Valor de la propiedad a establecer al objeto.
public class Reflection { public void FillObjectWithProperty(ref object objectTo, string propertyName, object propertyValue) { Type tOb2 = objectTo.GetType(); tOb2.GetProperty(propertyName).SetValue(objectTo, propertyValue); } }
Ya tenemos la función. No tiene ningún misterio, utiliza tres métodos básicos de reflexión que hablan por si solos (GetType, GetPropery, y SetValue).
Paso 2. Crear método de extensión.
Es el más complejo, podemos encontrar mucha información en google sobre los métodos de extensión. Pego la función, que está comentada con detalle.
public static class IENumerableExtensions { public static IEnumerable<T> CopyDataReader<T>(this IEnumerable<T> list, DbDataReader dr) { //Instanciar objecto reflec de la clase Reflection codificada antes Reflection reflec = new Reflection(); //Declarar un objeto "instance" tipo Object y una lista de objetos Object instance; List<Object> lstObj = new List<Object>(); //Recorrer dataReader while (dr.Read()){ //Crear instancia del objeto necesario. La instancia se crea obteniendo el //tipo de objeto T del objeto list, que es el propio objeto que llama al método de extensión. //Es decir se infiere el tipo T y se instancia instance= Activator.CreateInstance(list.GetType().GetGenericArguments()[0]); //Se recorren todos los campos de cada fila del dataReader, y mediante //el objeto reflec (método del primer paso) rellenamos el objeto instance con los valores //del datareader foreach (DataRow drow in dr.GetSchemaTable().Rows){ reflec.FillObjectWithProperty(ref instance, drow.ItemArray[0].ToString(), dr[drow.ItemArray[0].ToString()]); } //Añadir objeto instance a la lista lstObj.Add(instance); } //Convertir la lista de objetos (lstObj) en la lista List<T> resultante(lstResult) List<T> lstResult = new List<T>(); foreach (Object item in lstObj){ lstResult.Add((T)Convert.ChangeType(item, typeof(T))); } return lstResult; } }
Paso 3. Llamar al método de extensión.
Dado un dataReader (dr)
var listaTipoT= new List<T>(); var listaResult = listaTipoT.CopyDataReader(dr).ToList();
Y ya tenemos un List T !!