0

所以我有数千个通用类型 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),我可以一遍又一遍地重用它。

4

3 回答 3

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

于 2012-05-16T14:39:37.943 回答
3

我尝试使用表达式树,但据我了解,我必须为要设置的每个值生成一棵树,这不是很好。

为什么不?您基本上可以List<Tuple<string, Action<object>>>通过为T. 然后您遍历列表并获取每个属性的项目,然后调用相应的操作。

我在MiscUtilPropertyCopy有一门课,它做的事情非常相似——你可能想看看它以获得灵感。

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

于 2012-05-16T14:39:06.373 回答
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
);

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

当您使用它时,您可能可以通过编译另一个表达式树而不是Activator.CreateInstance().

于 2012-05-16T14:38:08.890 回答