我創建了一個散列表來緩存反射結果。第一次,需要調用GetProperties並將結果存儲到hastable中。接下來,首先檢查ListInfo對象的哈希表。如果存在,請使用它。如果不是,則調用GetProperties。
我使用它來將數據讀取器映射到實體列表。
我的實施基於:A Defense on Reflection in .Net,作者:Nick Harrison(http://www.simple-talk.com/dotnet/.net-framework/a-defense-of-reflection-in-.net/)。
那麼,它就在那裏:
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;
}
}
然後,我把它從我的DataAcces層,像這樣:
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);
}
所以,這樣一來,DAL得到一個DataReader,圖吧到業務實體列表,並將其返回到業務邏輯層。
這個類(MapeadorDataReaderListaObjetos)有一些問題依然,特別是在:
info.SetValue(newObject, _valor, null);
NEWOBJECT和_valor必須是同一類型,否則你會從System.Int64得到一個異常(轉換爲System.Int32,例如,如果您的實體屬性是Int32,並且它在數據庫表中的對應字段是bigint)。
另外,如果一個實體屬性是另一個實體,這將不起作用,因爲datareaders不返回實體對象。
很明顯,這可以改進。
關於反思和代表,我發現這篇文章:反思 - 慢還是快?演示的解決方案,通過阿布舍克蘇爾,在 http://www.abhisheksur.com/2010/11/reflection-slow-or-faster-demonstration.html
另外一個很好的文章是:道奇常見性能陷阱工藝迅速應用,喬爾Pobar,在http://msdn.microsoft.com/en-us/magazine/cc163759.aspx。
希望這會有所幫助。
您的回答暗示了我正確的方向(如何緩存PropertyInfo),它實際上比GetProperty更快(沒有時間它,但我的頁面的響應速度似乎有所提高)。 – Alex 2009-07-30 06:39:52