В данной статье рассматривается проблема заполнения полей класса, использующих тип данных Nullable<T>, с помощью технологии RTTI (Runtime Type Information) в среде разработки Delphi, с использованием библиотеки NEON от Paolo Rossi.
Оригинальный запрос пользователя
Пользователь столкнулся с проблемой при попытке заполнить поля класса, использующие тип Nullable<T>, данными из базы данных с помощью RTTI. В коде, предоставленном пользователем, используется процедура DatasetToObject, которая должна заполнить свойства объекта TMyClass данными из TFDQuery. Однако, несмотря на использование RTTI, заполнение полей класса не происходит.
Контекст проблемы
В библиотеке NEON определен тип Nullable<T>, который представляет собой запись с полями FValue и FHasValue. Существуют перегруженные конструкторы для создания экземпляра Nullable<T> и методы для работы с ним, включая SetValue.
Анализ проблемы
Проблема заключается в неправильном использовании RTTI для установки значений свойств класса. В частности, пользователь пытается вызвать метод SetValue через RTTI, но делает это некорректно, вызывая AsInteger на результате вызова метода, что приводит к исключению.
Подтвержденный ответ
Для корректной работы с Nullable<T> и RTTI необходимо использовать следующий подход:
Получить свойство через RTTI с помощью GetValue.
Вызвать метод SetValue для полученной записи, передав в него новое значение.
Установить измененную запись обратно в свойство объекта с помощью SetValue.
Также, для упрощения процесса, можно сделать свойство Value записи Nullable<T> читаемым и записываемым, что позволит установить значение напрямую через RTTI.
Альтернативный ответ (рекомендуемый)
Изменить определение свойства Value на читаемое и записываемое, чтобы напрямую установить значение через RTTI:
property Value: T read GetValue write SetValue;
Затем, в процедуре DatasetToObject, получить свойство через RTTI и установить в него значение, используя метод SetValueProp:
Важно использовать GetReferenceToRawData при вызове SetValueProp, чтобы избежать ошибки несовместимых типов.
Пример кода
procedure DatasetToObject(AObject: TObject; AQuery: TFDQuery);
var
n: Integer;
LRttiContext: TRttiContext;
LRttiType: TRttiType;
LRttiProperty: TRttiProperty;
LValue: TValue;
LRttiValueProp: TRttiProperty;
begin
LRttiContext := TRttiContext.Create;
try
LRttiType := LRttiContext.GetType(AObject.ClassType);
for n := 0 to AQuery.FieldCount - 1 do
begin
LRttiProperty := LRttiType.GetProperty(AQuery.Fields[n].FieldName);
if (LRttiProperty <> nil) and (LRttiProperty.PropertyType.TypeKind = tkRecord) and
(LRttiProperty.PropertyType.Name = 'Nullable<System.Integer>') then
begin
LValue := LRttiProperty.GetValue(AObject);
LRttiValueProp := LRttiContext.GetType(LValue.TypeInfo).GetProperty('Value');
LRttiValueProp.SetValue(LValue.GetReferenceToRawData, AQuery.Fields[n].AsInteger);
LRttiProperty.SetValue(AObject, LValue);
end;
end;
finally
LRttiContext.Free;
end;
end;
Заключение
При работе с Nullable<T> и RTTI важно корректно использовать методы и свойства записей, а также правильно обращаться к ним через RTTI. Предложенные выше решения позволят успешно заполнить поля класса данными из базы данных.
Проблема связана с заполнением полей класса, использующих тип данных `Nullable`, значениями из базы данных в среде Delphi с использованием библиотеки NEON и технологии RTTI, где неправильное использование RTTI приводит к ошибке при установке значений
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.