所以我有数以千计的通用类型T的对象,我想将它们转换为我得到的对象数组。 所以我必须得到属性列表T,并为每个属性设置值到数组上相应的对象
for (int i = 0; reader.Read(); i++)
{
T tmp = (T)Activator.CreateInstance(typeof(T));
foreach (var prop in properties)
{
prop.SetValue(tmp, reader.GetValue(reader.GetOrdinal(prop.Name)), null);
}
}
读者是一个DataReader。我遇到的问题是 prop.SetValue 很慢(占总执行时间的50%),I've been told使用动态方法或表达式树,我尝试使用表达式树但是根据我的理解,我必须为我想要设置的每个值生成一个树,这不会那么好。 所以动态方法是另一种选择。理想情况下,我需要创建一个方法 SetProp(object,propertyName,value),我可以一遍又一遍地重复使用。
答案 0 :(得分:4)
看FastMember;要么“按原样”使用它,要么窃取所有代码(DynamicMethod
等)。它完成了所有这些,内置了反射缓存等。示例用法:
var accessor = TypeAccessor.Create(typeof(T));
for (int i = 0; reader.Read(); i++)
{
T tmp = (T)Activator.CreateInstance(typeof(T));
foreach (var prop in properties)
{
accessor[tmp, propName] = newValue; // fill in name/value here
}
}
或者 - 使用像dapper-dot-net这样的东西,和处理所有物化(因为这显然是数据访问代码)。
答案 1 :(得分:3)
我尝试使用表达式树,但据我所知,我必须为我想要设置的每个值生成一个树,这不会那么好。
为什么不呢?您基本上通过为List<Tuple<string, Action<object>>>
中的每个属性创建(然后编译)表达式树来构建T
。然后迭代列表并获取每个属性的项目,然后调用相应的操作。
我在MiscUtil中有一个PropertyCopy
课程,它做了类似的事情 - 你可能想看看它是否有灵感。
或者,从.NET 4开始,您可以构建一个{em} all 属性设置的Block
表达式树。
答案 2 :(得分:0)
您可以为每个属性创建一个表达式树 只需将该值作为参数:
var instance = Expression.Parameter(typeof(T));
var value = Expression.Parameter(typeof(object));
var setter = Expression.Lambda(
Expression.SetProperty(instance, Expression.Cast(value, prop.PropertyType)),
instance, value
);
您可以为每个实例类型创建和编译这些表达式树(通常在static generic class中)。
当你接触它时,你可以通过编译另一个表达式树而不是Activator.CreateInstance()
来使它更快。