Creé una tabla hash para almacenar en caché los resultados de la reflexión. La primera vez, es necesario hacer una llamada a GetProperties y almacenar los resultados en el hastable. Los próximos tiempos, primero verifique la tabla hash para los objetos List of PropertyInfo. Si existe, úselo. Si no, invoque GetProperties.
Utilizo esto para asignar un lector de datos a una lista de entidades.
Mi implementación se basa en: A Defense on Reflection in .Net, por Nick Harrison (http://www.simple-talk.com/dotnet/.net-framework/a-defense-of-reflection-in-.net/).
Por lo tanto, ahí está:
public class MapeadorDataReaderListaObjetos
{
private Hashtable properties;
private Hashtable Properties
{
get
{
if (properties == null)
properties = new Hashtable();
return properties;
}
set { properties = value; }
}
private void LoadProperties(object targetObject, Type targetType)
{
var flags = BindingFlags.DeclaredOnly| BindingFlags.Instance| BindingFlags.Public;
if (properties == null)
{
List<PropertyInfo> propertyList = new List<PropertyInfo>();
PropertyInfo[] objectProperties = targetType.GetProperties(flags);
foreach (PropertyInfo currentProperty in objectProperties)
{
propertyList.Add(currentProperty);
}
properties = new Hashtable();
properties[targetType.FullName] = propertyList;
}
if (properties[targetType.FullName] == null)
{
List<PropertyInfo> propertyList = new List<PropertyInfo>();
PropertyInfo[] objectProperties = targetType.GetProperties(flags);
foreach (PropertyInfo currentProperty in objectProperties)
{
propertyList.Add(currentProperty);
}
properties[targetType.FullName] = propertyList;
}
}
public void MapearDataReaderListaObjetos <T> (IDataReader dr, List<T> lista) where T: new()
{
Type businessEntityType = typeof(T);
List<T> entitys = new List<T>();
T miObjeto = new T();
LoadProperties(miObjeto, businessEntityType);
List<PropertyInfo> sourcePoperties = Properties[businessEntityType.FullName] as List<PropertyInfo>;
while (dr.Read())
{
T newObject = new T();
for (int index = 0; index < dr.FieldCount; index++)
{
for (int _indice = 0; _indice < sourcePoperties.Count; _indice++)
{
if (sourcePoperties[_indice].Name.ToUpper() == dr.GetName(index).ToUpper());
{
string _tipoProp = sourcePoperties[_indice].PropertyType.ToString();
PropertyInfo info = sourcePoperties[_indice] as PropertyInfo;
if ((info != null) && info.CanWrite)
{
info.SetValue(newObject, dr.GetValue(index), null);
}
}
}
}
entitys.Add(newObject);
}
dr.Close();
lista = entitys;
}
}
Entonces, lo llamo de mi DataAcces capa, de esta manera:
public List <Entities.ENFactura> ListaxIdFactura (SqlTransaction Tr, Entities.ENFactura oBEFactura)
{
SqlConnection Cn = new SqlConnection();
Cn = _Connection.ConexionSEG();
List<Entities.ENFactura> loBEFactura = new List<Entities.ENFactura>();
using (Cn)
{
Cn.Open();
SqlDataReader drd = (odaSQL.fSelDrd(Cn, Tr, "Pa_CC_Factura_Listar_x_IdProveedor", oBEFactura));
if (drd != null)
{
if (drd.HasRows)
{
mapeador.MapearDataReaderListaObjetos <ENFactura>(drd, loBEFactura);
}
}
}
return (loBEFactura);
}
Así, de esta manera, el DAL consigue un datareader, trazarlo a una lista de entidades comerciales y devuélvala a la Capa lógica de negocios.
Esta clase (MapeadorDataReaderListaObjetos) tiene algunos problemas todavía, sobre todo en:
info.SetValue(newObject, _valor, null);
newObject y _valor deben ser del mismo tipo o obtendrá una excepción (conversión de System.Int64 a System.Int32, en caso de que la propiedad de su entidad sea Int32 y su campo correspondiente en la tabla de la base de datos sea bigint, por ejemplo).
Además, si una propiedad de entidad es otra entidad, esto no funcionará, porque los lectores de datos no devuelven objetos de entidad.
Obviamente, esto se puede mejorar.
En cuanto a la reflexión y los delegados, encontré este artículo: Reflexión: ¿lenta o rápida? Demostración con soluciones, por Abhishek Sur, en http://www.abhisheksur.com/2010/11/reflection-slow-or-faster-demonstration.html
Otro buen artículo es: Rendimiento trampas de Dodge Common Craft Aplicaciones Speedy, por Joel POBAR, en http://msdn.microsoft.com/en-us/magazine/cc163759.aspx.
Espero que esto ayude.
Su respuesta me indicó en la dirección correcta (cómo almacenar PropertyInfo) que es en realidad más rápido que GetProperty (aún no ha llegado el momento, pero la capacidad de respuesta de mi página parece mejorada) – Alex
Si puede caché delegados llamar a la propiedad en un tipo seguro, que bien puede hacer que sea más rápido de nuevo. Definitivamente tiempo, aunque ... –