reflection:使用动态方法设置大量对象的属性

所以我有数以千计的通用类型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); } } 

reader是一个DataReader。 我遇到的问题是prop.SetValue很慢(占总执行时间的50%), 我被告知使用动态方法或表达树,我尝试使用表达式树,但从我的理解,我必须为我想要设置的每个值生成一个树,这不会那么好。 所以动态方法是另一种选择。 理想情况下,我需要创建一个方法SetProp(object,propertyName,value) ,我可以一遍又一遍地重用它。

看看FastMember ; 或者“按原样”使用它,或者窃取所有代码( DynamicMethod等)。 它完成了所有这些,内置了reflection缓存等。示例用法:

 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的东西,这样做处理所有物化(因为这显然是数据访问代码)。

我尝试使用表达式树,但据我所知,我必须为我想要设置的每个值生成一个树,这不会那么好。

为什么不? 您基本上通过为T每个属性创建(然后编译)表达式树来构建List>> 。 然后迭代列表并获取每个属性的项目,然后调用相应的操作。

我在MiscUtil中有一个PropertyCopy类,它有一些非常相似的东西 – 你可能想看看它的灵感。

或者,从.NET 4开始,您可以构建一个Block表达式树,它可以完成所有属性设置。

您可以为每个属性创建单个表达式树。
只需将值作为参数:

 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 ); 

您可以为每个实例类型创建和编译这些表达式树(通常在静态generics类中 )。

当你在它的时候,你可以通过编译另一个表达式树而不是Activator.CreateInstance()来使它更快。