反思:设置大量的对象使用动态方法的性质(Reflection: Setting properties

2019-09-17 06:37发布

所以,我有成千上万的泛型类型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可悲的是缓慢的(像消耗的总excecution时间的50%), 有人告诉我,使用动态方法或表达式树,我尝试使用表达式目录树但是从我了解我必须生成我要设置的每个值,就不会这么好一棵树。 所以动态方法是另一种选择。 理想的情况是我需要创建一个方法SetProp(对象,propertyName的,价值),我可以重用一遍又一遍。

Answer 1:

看看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
    }
}

或者-使用像短小精悍点网,这项作业处理所有的物化(因为这显然是数据访问代码)。



Answer 2:

我尝试使用表达式目录树但是从我了解我必须生成我要设置的每个值,就不会这么好一棵树。

为什么不? 你会基本建成一个List<Tuple<string, Action<object>>>通过为每个属性创建(然后编译)表达式树T 。 然后,你遍历列表,并获取该项目的每个属性,然后调用相应的动作。

我有一个PropertyCopy类MiscUtil这确实非常类似的东西-你可能想看看那个灵感。

此外,作为.NET 4中,你可以建立一个单一的Block表达式树,完成了所有的属性设置。



Answer 3:

你可以为每个属性创建一个表达式树。
只取值作为参数:

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

您可以创建和每一次实例类型(通常在编译这些表达式树静态泛型类 )。

当你在这,你也许可以使它更快通过编译另一个表达式树,而不是Activator.CreateInstance()



文章来源: Reflection: Setting properties of lots of objects using Dynamic Methods
标签: c# reflection