在处理大量数据时,性能优化变得尤为重要。本文将介绍一种方法,通过使用表达式树 (Expression Trees) 来优化将未知类型的对象列表映射到DataTable的性能。
假设有一个对象列表,每个对象包含多个属性。目标是将这些对象映射到DataTable中。在不使用表达式树的情况下,可能会使用反射来获取对象的属性值,但这通常会导致性能问题。
原始的方法可能看起来像这样:
var properties = objectType.GetProperties();
foreach (object obj in objects)
{
    foreach (var property in properties)
    {
        property.GetValue(obj, null);
    }
}
    
这种方法在处理一百万对象时,在机器上大约需要6000毫秒。
如果对象的类型在编译时已知,可以使用Lambda表达式来获取属性值。但是,由于对象的类型在编译时未知,需要为每个属性构建一个表达式树。
以下是构建表达式树的示例代码:
Expression> expression = o => ((SomeClass)o).Property1;
     
这个表达式将参数类型从object转换为目标对象类型,并获取其属性值。结果也需要转换回object类型,以匹配表达式的返回值类型。
对于同一种类型的对象,可以这样构建属性访问器的集合:
var compiledExpressions = (
    from property in properties
    let objectParameter = Expression.Parameter(typeof(object), "o")
    select Expression.Lambda>(
        Expression.Convert(
            Expression.Property(
                Expression.Convert(
                    objectParameter,
                    objectType
                ),
                property
            ),
            typeof(object)
        ),
        objectParameter
    ).Compile()).ToArray();
     
虽然看起来有点复杂,但使用这种方法读取所有对象的所有属性值:
foreach (object obj in objects)
{
    foreach (var compiledExpression in compiledExpressions)
    {
        compiledExpression(obj);
    }
}
    
在机器上只需要大约150毫秒。这比之前的方法快了2.5%。