2012-05-16 2 views
0

Итак, у меня есть тысячи объектов общего типа T, и я хочу передать их в массив объектов, которые у меня есть. Так что я должен получить список свойств T, и для каждого свойства установите значение соответствующего объекта в массивеReflection: настройка свойств множества объектов с использованием динамических методов

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, чтобы использовать динамические методы или деревья выражений, я попытался использовать деревья выражений, но из того, что понял, мне нужно сгенерировать один дерево для каждого значения, которое я хочу установить, что было бы не так хорошо. Таким образом, Dynamic Methods - это другой вариант. В идеале мне нужно будет создать метод SetProp (object, propertyName, value), который я могу повторно использовать снова и снова.

+0

* лично *, я бы сказал, «не используйте GetOrdinal для каждой ячейки», хотя это не будет иметь большого значения, однако, поскольку это явно «код чтения данных», который имеет совпадение 1: 1 между имя свойства и имя столбца, я действительно предлагаю вам посмотреть на dapper-dot-net; он предназначен для ** именно ** этого сценария и делает доступ к данным просто безболезненным. Это инструмент, который мы написали и широко используем для большинства наших данных - здесь, в Stack Overflow. –

ответ

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

в качестве альтернативы - использовать что-то вроде щеголеватой-точки-сети, что делает это и обрабатывают все материализации (так как это, очевидно, данные. -код доступа).

+0

Только +1, потому что я не могу проголосовать 10 раз, от быстрого взгляда он отлично работает ... Я ** должен ** обновить свой код! –

+1

Для этого объекта-объекта существует также «ObjectAccessor»; Я также должен отметить, что он поддерживает также «динамический» API (так что вы можете использовать его для связи с объектом, связанным со временем выполнения) –

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().

3

Я попытался использовать деревья выражений, но из того, что понял, мне нужно сгенерировать одно дерево для каждого значения, которое я хочу установить, что было бы не так хорошо.

Почему нет? В основном вы создаете List<Tuple<string, Action<object>>>, создав (а затем скомпилировав) дерево выражений для каждого свойства в T. Затем вы перебираете список и выбираете элемент для каждого свойства, а затем вызываете соответствующее действие.

У меня есть класс PropertyCopy в MiscUtil, который делает что-то очень похожее - вы можете посмотреть на это для вдохновения.

В качестве альтернативы, с .NET 4 вы можете построить одно дерево выражений Block, которое делает все настройкой свойств.

+0

Я не думаю, что я использую это решение, но я обязательно это проверю, спасибо! – gosukiwi

Смежные вопросы