2011-01-26 3 views
5

В приложении у нас есть набор объектов ORM и набор бизнес-объектов. Большую часть времени мы просто делаем член по копии экземпляра. В других случаях мы обрабатываем данные немного. Например:Member by Member copy

tEmployee emp = new tEmployee(); 
emp.Name = obj.Name; 
emp.LastName = obj.LastName; 
emp.Age = obj.Age; 
emp.LastEdited = obj.LastEdited.ToGMT(); 

Теперь это прекрасно работает, и довольно быстро, но не совсем немногословен, когда речь идет о кодировании. Некоторые из наших объектов имеют до 40 членов, поэтому выполнение такой копии может стать довольно утомительным. Конечно, вам нужно только два метода для двух-> конверсий, но я хотел бы найти лучший способ сделать это.

Отражение - это естественный выбор, но по эталону я обнаружил, что время выполнения было примерно на 100 раз медленнее при использовании отражения.

Есть ли лучший способ сделать это?

Уточнение: Я перехожу от одного типа к другому. В приведенном выше примере obj имеет тип BLOGICEmployee и emp имеет тип tEmployee. Они разделяют имена участников, но это все.

ответ

5

Возможно, вы захотите зарегистрироваться AutoMapper.

+0

+1: Я использовал Automapper в производственных приложениях точно для цели, описанной OP, и ее * awesome *. – Juliet

1

Object.MemberwiseClone может быть полезно, если все, что вам нужно, это мелкий клон. Не уверен, насколько хорошо он работает, и, очевидно, для любых сложных объектов потребуется дополнительная обработка для обеспечения правильной копии.

2

Отражение можно ускорить, если вы используете делегатов. В принципе, вы можете создать пару делегатов для каждой пары getter/setter, а затем выполнить их - скорее всего, будет очень быстро. Используйте Delegate.CreateDelegate, чтобы создать делегат, заданный MethodInfo и т. Д. В качестве альтернативы вы можете использовать деревья выражений.

Если вы создаете объект , у меня уже есть куча кода для этого в MiscUtil. (Он находится в классе MiscUtil.Reflection.PropertyCopy.) Это использует отражение для свойств для копирования в существующие объекты, но делегат для преобразования объектов в новые. Очевидно, вы можете приспособить его к вашим потребностям. Я уверен, что если бы я писал сейчас я смог бы избежать отражения для копирования с помощью Delegate.CreateDelegate, но я не о том, чтобы изменить его :)

0

Смотрите, если вы можете использовать this

резюмировать : и класс должен быть Сериализуемым, чтобы это работало.

public static T DeepClone<T>(T obj) 
{ 
using (var ms = new MemoryStream()) 
{ 
    var formatter = new BinaryFormatter(); 
    formatter.Serialize(ms, obj); 
    ms.Position = 0; 

    return (T) formatter.Deserialize(ms); 
} 
} 
+1

Он не хочет создавать копию того же типа - он хочет скопировать набор элементов из типа A в тип B, где оба имеют очень похожие элементы. –

2

Рассмотрите возможность использования AutoMapper. Из документации:

.. AutoMapper работает лучше всего, пока имена членов совпадают с членов типа источника в. Если у вас есть источник, который называется «FirstName», , это автоматически будет сопоставлено с адресом с именем «FirstName».

Это позволит вам сэкономить много явного отображения и AutoMapper конечно позволяет настройки конкретных отображений вдоль линий:

Mapper.CreateMap<Model.User, Api.UserInfo>() 
     .ForMember(s => s.Address, opt => opt.Ignore()) 
     .ForMember(s => s.Uri, opt => opt.MapFrom(c => HttpEndpoint.GetURI(c))) 
3

Если вы не против того, чтобы быть немного замедлится в первый раз, вы можете компилировать лямбда-выражение:

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