Files
MycLib/Src/Data/Myc.Data.Types.RTTI.pas
T
Michael Schimmel afb8f459c6 Types-JSON
2025-08-27 18:00:01 +02:00

85 lines
2.9 KiB
ObjectPascal

unit Myc.Data.Types.RTTI;
interface
uses
System.SysUtils,
System.RTTI,
Myc.Data.Types;
function AsTValue(const Value: TDataType.TValue): TValue;
function RttiTypeToDataType(rttiType: TRttiType): TDataType;
implementation
uses
System.TypInfo,
System.Math;
// Recursively converts a TRttiType to an IDataType.
function RttiTypeToDataType(rttiType: TRttiType): TDataType;
var
i: Integer;
begin
// Convert an RTTI type representation to its corresponding IDataType.
case rttiType.TypeKind of
tkInteger, tkInt64, tkChar, tkWChar: Result := TDataType.Ordinal;
tkFloat:
if (rttiType.Handle = TypeInfo(TDateTime)) then
Result := TDataType.Timestamp
else
Result := TDataType.Float;
tkString, tkWideString, tkUString: Result := TDataType.Text;
tkEnumeration:
begin
var enumType := rttiType as TRttiEnumerationType;
var names := enumType.GetNames;
var identifiers: TArray<string>;
SetLength(identifiers, Length(names));
for i := 0 to High(names) do
identifiers[i] := names[i];
Result := TDataType.EnumOf(enumType.Name, identifiers);
end;
tkDynArray:
begin
var arrayType := rttiType as TRttiDynamicArrayType;
Result := TDataType.ArrayOf(RttiTypeToDataType(arrayType.ElementType));
end;
tkRecord:
begin
var recordType := rttiType as TRttiRecordType;
var fields := recordType.GetFields;
var recordFields: TArray<TDataRecordField>;
SetLength(recordFields, Length(fields));
for i := 0 to High(fields) do
recordFields[i] := TDataRecordField.Create(fields[i].Name, RttiTypeToDataType(fields[i].FieldType));
Result := TDataType.RecordOf(recordFields);
end;
else
// Raise an exception for unsupported types.
raise ENotSupportedException.CreateFmt(
'Type "%s" (Kind: %s) is not supported for RTTI-based record creation.',
[rttiType.Name, GetEnumName(TypeInfo(TTypeKind), Ord(rttiType.TypeKind))]);
end;
end;
{ TValueHelper }
function AsTValue(const Value: TDataType.TValue): TValue;
begin
case Value.DataType.Kind of
dkVoid: Result := TValue.Empty;
dkOrdinal: Result := TValue.From<Int64>(Value.AsOrdinal.Value);
dkFloat: Result := TValue.From<Double>(Value.AsFloat.Value);
dkText: Result := TValue.From<string>(Value.AsText.Value);
dkTimestamp: Result := TValue.From<TDateTime>(Value.AsTimestamp.Value);
dkEnum: Result := TValue.From<Integer>(Value.AsEnum.Value);
dkMethod: Result := TValue.From<TDataMethodProc>(Value.AsMethod.Value);
else
raise EInvalidOpException.Create('Unsupported data type');
end;
end;
end.