Копирование моделей между слоями

При обходе слоев очень утомительно выполнять назначения справа налево как способ заполнения моделей. Например:

employeeViewModel.FirstName = employeeModel.FirstName;
employeeViewModel.LastName = employeeModel.LastName;
...

Итак, мы можем построить ModelCopier, который использует отражение для копирования моделей:

var employeeViewModel = ModelCopier.Copy<EmployeeViewModel>(employeeModel);

Этот метод значительно упрощает задачу. Тем не менее, есть несколько вещей, которые весьма беспокоят насчет этого:

  • Мы фактически утратили способность отслеживать использование свойств на объектах источника и назначения. Например, при поиске использования (в Resharper) свойства FirstName не выявляются случаи ModelCopier.
  • Если мы изменим имя свойства в классе источника или назначения, мы можем непреднамеренно вызвать исключения времени выполнения, так как мы можем не осознавать, что нам нужно обновить как исходный, так и целевой класс.

На одном конце спектра мы можем использовать отражение, которое очень легко, но за счет ремонтопригодности. Противоположный конец спектра очень утомителен, но очень ремонтопригоден.

Отражение (легкое и опасное) <-----> Прямое назначение (утомительное и удобное в обслуживании)

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

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

РЕДАКТИРОВАТЬ:

Пожалуйста, поймите, что этот вопрос не о том, какой инструмент картирования использовать. Я' я пытаюсь понять, как мы можем пользоваться преимуществами картографирования на основе отражений, а также преимуществами сопровождения, которое обеспечивается прямым назначением (или контрактом карты свойств).

8
задан Jason Berkan 27 August 2010 в 16:38
поделиться

5 ответов

Вероятно, компилятор не выполняет необходимые тесты по всему коду... вот тут-то и пригодится модульное тестирование. Если вы определили тест для преобразования между классами в разных слоях (да, все возможные преобразования, которые вам нужно выполнить, иначе как вы можете быть уверены, что ваш подход к отражению будет работать в любой ситуации после запуска?), просто run the test сообщит разработчику, изменившему имя свойства, что решение больше не проходит все тесты. Вы должны запускать каждый тест (модульный, а не интеграционный) каждый раз, когда хотите проверить исходный код... и это не должно занимать пару месяцев кодирования :))

Поэтому я действительно голосую за использование подхода отражения, приправленного ложкой подхода модульного тестирования.

3
ответ дан 5 December 2019 в 12:06
поделиться

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

0
ответ дан 5 December 2019 в 12:06
поделиться

ваши требования выходят за рамки времени выполнения (реализации) как такового, поскольку вам (и всем нам) нужны графики зависимостей и т. д. Это означает, что динамическое обнаружение с отражением отключено. Кажется, вам нужно решение времени компиляции. Помимо предложения @amaca о плагине для генерации кода (который вы можете легко написать), какие еще могут быть варианты?

0
ответ дан 5 December 2019 в 12:06
поделиться

Интересно, нашел ли кто-нибудь компромисс, обеспечивающий простоту использование отражения для копирования с ремонтопригодность прямого назначения.

Похоже, вы пытаетесь получить свой пирог и съесть его.

Это проблема, с которой динамические языки сталкиваются каждый день. Волшебной таблетки не существует. Либо выполняйте присваивания влево-вправо и получайте защиту компилятора, либо оберните критические присваивания в модульные тесты.

Моя интуиция подсказывает мне, что это проблема дизайна, а не кода.

1
ответ дан 5 December 2019 в 12:06
поделиться

Серьезно, используйте AutoMapper. Это позволяет настроить преобразования из одного типа в другой тип. Любые изменения в именах свойств нарушат конфигурацию автосопоставителя, что не произойдет с отражением:

Mapper.CreateMap<SiteDto, SiteModel>();
Mapper.CreateMap<SiteModel, SiteDto>();

Затем, чтобы сопоставить и из, вы просто делаете следующее:

SiteDto dto = Mapper.Map<SiteModel, SiteDto>(targetModel);
SiteModel model = Mapper.Map<SiteDto, SiteModel>(targetDto);
10
ответ дан 5 December 2019 в 12:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: