property.setvalue()有哪些替代方案?我读过它很慢。我用它来将IDataReader映射到POCO对象。
这是代码的截断版本。这里的一切对我来说都是新鲜的。我知道有很多框架可以完成这项任务。但是,我们不能使用它们。
public class DbAutoMapper<T>
{
public IEnumerable<T> MapToList(IDataReader reader)
{
var list = new List<T>();
while (reader.Read())
{
var obj = Activator.CreateInstance<T>();
foreach (PropertyInfo prop in obj.GetType().GetProperties())
{
foreach (var attribute in prop.GetCustomAttributes(true))
{
prop.SetValue(obj, value, null);
}
}
list.Add(obj);
}
return list;
}
}
答案 0 :(得分:5)
首先:当你不使用属性时,为什么要重复每个属性的反射?
第二:假设您打算按名称,列到属性(这不是代码当前所做的)映射,请考虑dapper之类的工具,为您完成所有这些工作,包括缓存的高性能反射 - 发射。它还将为您处理命令本身。例如:
string region = "North";
var customers = conn.Query<Customer>(
@"select * from Customers where Region = @region",
new { region } // full parameterization, the easy way
).ToList();
如果您需要更多控制,请考虑FastMember,它提供快速成员访问(同样,反射 - 发射),但不是特定于数据访问:
var accessor = TypeAccessor.Create(typeof(T));
string propName = // something known only at runtime
while( /* some loop of data */ ) {
var obj = new T();
foreach(var col in cols) {
string propName = // ...
object cellValue = // ...
accessor[obj, propName] = cellValue;
}
yield return obj;
}
答案 1 :(得分:1)
我想到了一些方法......
跳过反思
public class DbAutoMapper<T> where T : IInitFromReader, new()
{
public IEnumerable<T> MapToList(IDataReader reader)
{
var list = new List<T>();
while (reader.Read())
{
IInitFromReader obj = new T;
obj.InitFromReader(reader);
list.Add(obj);
}
return list;
}
}
然后,您必须在每个权利对象中实现InitFromReader。显然,这会减少反射的好处(代码较少)。
代码生成
为(InitFromReader)维护此代码很痛苦,因此您可以选择生成它。这在很多方面为您提供了两全其美的优势: