Delphi: Wie wird die Länge eines dynamischen Arrays mit RTTI-Zugriff mit DynArraySetLength festgelegt?
Ich möchte die Länge eines dynamischen Arrays festlegen, wie in empfohlendieser Beitrag. Ich habe zwei Klassen TMyClass und die zugehörige TChildClass als definiert
TChildClass = class
private
FField1: string;
FField2: string;
end;
TMyClass = class
private
FField1: TChildClass;
FField2: Array of TChildClass;
end;
Die Array-Erweiterung wird implementiert als
var
RContext: TRttiContext;
RType: TRttiType;
Val: TValue; // Contains the TMyClass instance
RField: TRttiField; // A field in the TMyClass instance
RElementType: TRttiType; // The kind of elements in the dyn array
DynArr: TRttiDynamicArrayType;
Value: TValue; // Holding an instance as referenced by an array element
ArrPointer: Pointer;
ArrValue: TValue;
ArrLength: LongInt;
i: integer;
begin
RContext := TRTTIContext.Create;
try
RType := RContext.GetType(TMyClass.ClassInfo);
Val := RType.GetMethod('Create').Invoke(RType.AsInstance.MetaclassType, []);
RField := RType.GetField('FField2');
if (RField.FieldType is TRttiDynamicArrayType) then begin
DynArr := (RField.FieldType as TRttiDynamicArrayType);
RElementType := DynArr.ElementType;
// Set the new length of the array
ArrValue := RField.GetValue(Val.AsObject);
ArrLength := 3; // Three seems like a nice number
ArrPointer := ArrValue.GetReferenceToRawData;
DynArraySetLength(ArrPointer, ArrValue.TypeInfo, 1, @ArrLength);
{ TODO : Fix 'Index out of bounds' }
WriteLn(ArrValue.IsArray, ' ', ArrValue.GetArrayLength);
if RElementType.IsInstance then begin
for i := 0 to ArrLength - 1 do begin
Value := RElementType.GetMethod('Create').Invoke(RElementType.AsInstance.MetaclassType, []);
ArrValue.SetArrayElement(i, Value);
// This is just a test, so let's clean up immediatly
Value.Free;
end;
end;
end;
ReadLn;
Val.AsObject.Free;
finally
RContext.Free;
end;
end.
Da D2010 RTTI neu ist, vermutete ich, dass der Fehler davon abhängen könnte, ob ArrValue von der Klasseninstanz abgerufen wird, aber von der nachfolgendenWriteLn
druckt "TRUE", deshalb habe ich das ausgeschlossen. Enttäuschenderweise jedoch das gleicheWriteLn
meldet, dass die Größe von ArrValue 0 ist, was durch die "Index out of bounds" -Ausnahme bestätigt wird, die ich bekomme, wenn ich versuche, eines der Elemente im Array (durch) zu setzenArrValue.SetArrayElement(i, Value);
). Weiß jemand, was ich hier falsch mache? (Oder gibt es vielleicht einen besseren Weg, dies zu tun?) TIA!