Как вы сказали, в параметрах array of const
в текущем состоянии компилятора не допускается record
.
На самом деле, TVarRec.VType
значения не имеют vtRecord.
И сам тип Variant
не имеет типа varRecord
, обрабатываемого Delphi. В мире Windows существует такой тип варианта (например, структуры DotNet отображаются в тип vt_Record
в COM), но этот тип варианта не обрабатывается Delphi.
Что возможно, так это передать указатель на typeinfo записи, затем на запись:
case Params[i].VType of
vtPointer:
if (i<high(Params)) and (Params[i+1].VType=vtPointer) then
if Params[i].VPointer = TypeInfo(MyRecord) then begin
...
end;
Возможно, это не чудесный ответ, так как вы используете дженерики ... но, по крайней мере, для начала ... Во всех случаях, вот как я мог бы использовать это с предварительно универсальными компиляторами Delphi. Ключевое слово TypeInfo () уже было достаточно мощным и быстрее, чем «новая» реализация RTTI.
Другая возможность (совместимая с генериками) должна заключаться в добавлении некоторого идентификатора типа записи в содержимое записи. Затем передайте запись как указатель, прочитайте идентификатор и действуйте с ним, как ожидается:
case Params[i].VType of
vtPointer:
if Params[i].VPointer <> nil then
case PRecordType(Params[i].VPointer)^ of
aRecordType: ...
...
end;
Это можно сделать простым расширением исходного определения Nullable<T>
.
Постскриптум:
Использование записей в ORM, возможно, не лучшее решение ...
Модель class
является более продвинутой, чем модель record/object
в Delphi, и, поскольку ORM касается моделирования объектов, вы должны использовать лучшую доступную модель ООП, IMHO. Опираясь на классы вместо записей, вы можете иметь наследование , информацию о встроенном типе (с помощью метода Class
или просто с помощью PPointer(aObject)^
), значения, допускающие значения NULL, и виртуальные методы ( что очень удобно для ОРМ). Даже проблема параметров array of const
позволит напрямую обрабатывать такие типы vtObject
, а также выделенный виртуальный метод класса. ORM, основанный на записях, будет лишь способом сериализации строк таблицы, а не разработки вашего приложения с использованием наилучшей практики ООП. Что касается производительности, выделение памяти для экземпляров class
не является проблемой, если сравнивать с потенциальными проблемами копирования записей (функция _CopyRecord
RTL - вызывается скрытым образом компилятором, например, для параметров функции - может быть очень медленно ).
Например, в нашем ORM мы обрабатываем свойства динамического массива, даже динамические массивы записей в свойствах (Delphi не создает RTTI для опубликованных свойств записей, это еще одно противоречивое поведение текущего класса реализация). Мы сериализуем записей и динамических массивов в JSON или двоичные файлы со "старым" RTTI, и это работает очень хорошо. Лучшее из двух объектов мира под рукой.