Каковы преимущества использования Autopper?
Мой вопрос может быть глупым, но я уверен, что пропустил очень важную часть проблемы. Мне нужно сделать отображение объекта на объект (между классами домена, используемыми в проекте C#, и классами, которые отправляются флеш-клиентам).
Мой первый выбор был Automapper. Но у меня были некоторые проблемы с этим (вложенные свойства, не определяемый конструктор без параметров). Оказывается, не так просто сопоставить действительно сложный тип с автоматом.
Тогда мой вопрос: почему бы не реализовать такие методы, как:
ClassA GetClassAByClassB(ClassB pObj)
{
ClassA objA = new ClassA();
objA.Prop1 = pObj.Prop1;
objA.NestedType.Prop2 = pObj.Prop2;
//....Some more.....
return objA;
}
Он имеет тот же уровень гибкости, что и отображение, выполненное с использованием Automapper. Вы все еще должны указать, какое свойство из исходного объекта копируется в какие свойства объекта назначения. Вы просто делаете это, используя '=', а не лямбда-выражение.
Но если вы что-то измените в своих классах домена, вам все равно придется изменить эту часть "отображения". Итак, что является главным, что должно убедить меня в использовании Automapper (как я уже говорил в начале, я почти уверен, что упускаю что-то важное).
3 ответа
Потому что с AutoMapper вам не нужно реализовывать эти методы;-)
Ваш подход требует написания много
classA.propA = classB.propA;
classA.propB = classB.propB;
classA.propC = classB.propC;
classA.propD = classB.propD;
classA.propE = classB.propE;
AutoMapper использует соглашения, чтобы понять это сам. Более того, вам не нужно беспокоиться о pObj == null
(ваш код скинет NulLReferenceException
в этом случае).
Вы также можете определить преобразования на вашей карте (например, строка в DateTime).
Mapper.CreateMap<User, UserModel>().ForMember(d => d.LastLogin, c => c.MapFrom<DateTime?>(u => u.Credential.LastLogin));
AutoMapper также поддерживает вложенные свойства.
Подробнее здесь: Введение в AutoMapper и примеры
Единственное преимущество, которое, как утверждает AutoMapper, заключается в сопоставлении по соглашению. Вот цитата из "Введение и образцы AutoMapper"
"В этом и заключается прелесть AutoMapper. Когда ваши классы выровняются традиционным образом, ваша конфигурация отображения может быть настолько простой"
Эта выгода идет с ценой. Переименование или изменение как целевого, так и исходного свойства нарушит отображение и приведет к ошибкам во время выполнения, а не к ошибкам компиляции.
Если вы не можете полагаться на условное отображение, AutoMapper теряет свое преимущество. В этом случае я бы предпочел написать заводскую функцию, как показано ниже.
public static ClassA MapToClassA(this ClassB b)
{
return new ClassA()
{
propA = b.propA;
propB = b.propB;
propC = b.propC;
}
}
Тогда вы бы построить объект назначения как
var classA = classB.MapToClassA();
вместо
var classA = Mapper.Map<ClassB, ClassA>(classB)
Лично я предпочел бы фабричные функции, даже когда сопоставление соглашения возможно из-за его явности, читабельности и удобства отладки. Удачи при попытке выяснить, во втором случае, как ClassB отображается на ClassA, загружен ли профиль отображения, или почему существует исключение при вызове функции Map<>(), или почему некоторые свойства было присвоено неправильное значение.
Иногда с помощью картографов очень сложно отследить ошибки. Например, если мы неправильно опишем Employee в классе данных с Emplyee в классе модели представления, преобразователи типа крошечных преобразователей не выдают никаких исключений, если только мы явно не установим преобразователи как строгое сопоставление, и в течение этого времени код компилируется и работает отлично, но мы не в состоянии отследить ошибки. Такая ситуация редко возникает при ручном сопоставлении, поэтому ручное сопоставление объектов имеет некоторые преимущества перед автоматическим сопоставлением.