Как сопоставить свойства DTO со свойствами объекта домена при наличии иерархии классов в C#C#

Место общения программистов C#
Ответить
Anonymous
 Как сопоставить свойства DTO со свойствами объекта домена при наличии иерархии классов в C#

Сообщение Anonymous »

Введение
Проще говоря, предположим, что у нас есть 3 класса в предметной области (я называю их бизнес-объектами, BO). Я не учитываю конструкторы и прочее, более или менее важны только свойства.

публичный класс VehicleBo { общедоступная строка Производитель { get; набор; } } общественный класс CarBo: VehicleBo { общественный ИНТ PassengerCount {получить; набор; } } общественный класс TruckBo: VehicleBo { общественный двойной MaximumLoad {get; набор; } общественный bool HasTrailer {получить; набор; } } Тогда у нас есть только один объект DTO, который «агрегирует» все свойства из иерархии BO.

публичный класс VehicleDto { общедоступная строка Производитель { get; набор; } общественный ИНТ PassengerCount {получить; набор; } общественный двойной MaximumLoad {get; набор; } общественный bool HasTrailer {получить; набор; } // Соответствует дискриминатору, определенному в VehicleBo при сопоставлении BO с базой данных с помощью EF Core. общественная строка VehicleType {get; набор; } } Мы используем Entity Framework Core для сопоставления наших BO с таблицами в реляционной базе данных. Существует только одна таблица (Транспортные средства) для всех BO, т.е. VehicleBo, CarBo, TruckBo. Таблица Vehicles сопоставляется с сущностью VehicleBo, а остальные BO хранятся в Vehicles с использованием стратегии «Таблица по иерархии» (TPH).< /п> За кулисами Теперь я ищу хорошее и последовательное решение по этому поводу:

Когда пользователь просматривает содержимое таблицы Vehicles, он видит данные, хранящиеся в объекте DTO (VehicleDto). Для целей фильтрации и сортировки существует крошечная «структура», которая этим управляет. Он пытается «сопоставить» свойство DTO с соответствующим свойством BO, но очень простым способом — имена должны совпадать.

Например, для фильтра наш FE отправляет запрос (в символьном коде):

{ Тип: Транспортное средствоDto, Предикат: v => v.Производитель == "Форд" } Фреймворк преобразует это примерно так:

{ Тип: Транспортное средствоБо, Предикат: v => v.Производитель == "Форд" } (Обратите внимание на VehicleBo вместо VehicleDto) И он отправляет его в BE.

Здесь все просто, поскольку свойство Manufacturer находится как в DTO, так и в BO.

Однако это не относится, например, к PassengerCount.

FE отправляет:

{ Тип: Транспортное средствоDto, Предикат: v => v.PassengerCount > 2 } Фреймворк не может преобразовать это в:

{ Тип: Транспортное средствоБо, Предикат: v => v.PassengerCount > 2 } Поскольку свойство PassengerCount не существует в VehicleBo.

Поэтому на наш BE затем отправляется следующее:

{ Тип: Транспортное средствоБо, Предикат: v => ((CarBo) v).PassengerCount > 2 } Это нормально, EF прекрасно может преобразовать это в запрос SQL.
Вызов
Но я ищу элегантный способ дать нашей структуре подсказку относительно сопоставления «DTO-to-BO».

Первая идея — использование атрибутов.

публичный класс PropertyMappingAttribute : Атрибут { public Expression PropertySelector {get; } public PropertyMappingAttribute (Expression propertySelector) { PropertySelector = PropertySelector; } } // ... общественный класс VehicleDto { общедоступная строка Производитель { get; набор; } [PropertyMapping(v => ((CarBo) v).PassengerCount)] общественный ИНТ PassengerCount {получить; набор; } общественный двойной MaximumLoad {get; набор; } общественный bool HasTrailer {получить; набор; } // Соответствует дискриминатору, определенному в VehicleBo при сопоставлении BO с базой данных с помощью EF Core. общественная строка VehicleType {get; набор; } } К сожалению, в C# в настоящее время это невозможно. Для параметров атрибута мы должны использовать примитивные типы, такие как строка:

публичный класс PropertyMappingAttribute: Атрибут { общественная строка PropertySelector {get; } public PropertyMappingAttribute (строка propertySelector) { PropertySelector = PropertySelector; } } // ... общественный класс VehicleDto { общедоступная строка Производитель { get; набор; } [PropertyMapping("((CarBo) v).PassengerCount")] общественный ИНТ PassengerCount {получить; набор; } общественный двойной MaximumLoad {get; набор; } общественный bool HasTrailer {получить; набор; } // Соответствует дискриминатору, определенному в VehicleBo при сопоставлении BO с базой данных с помощью EF Core. общественная строка VehicleType {get; набор; } } Но последний подход неудобен и подвержен ошибкам.

Есть ли у вас предложения, как решить эту проблему элегантно, сохраняя при этом простоту и безопасность ввода?
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»