Je voudrais définir la longueur d'un tableau dynamique, comme suggéré dans this post. J'ai deux classes TMyClass et TChildClass liés définis commeDelphi: comment définir la longueur d'un tableau dynamique RTTI-accédé en utilisant DynArraySetLength?
TChildClass = class
private
FField1: string;
FField2: string;
end;
TMyClass = class
private
FField1: TChildClass;
FField2: Array of TChildClass;
end;
L'augmentation de tableau est mis en œuvre comme
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.
Étant nouveau D2010 RTTI, je soupçonne l'erreur pourrait dépendre de l'obtention ArrValue de l'instance de classe , mais les WriteLn
suivants imprime "TRUE", donc je l'ai exclu. Malheureusement, le même WriteLn
signale que la valeur de ArrValue est 0, ce qui est confirmé par l'exception "Index out of bounds" que j'obtiens en essayant de définir n'importe lequel des éléments du tableau (par l'intermédiaire de ArrValue.SetArrayElement(i, Value);
). Est-ce que quelqu'un sait ce que je fais mal ici? (Ou peut-être y at-il une meilleure façon de le faire?) TIA!
Merci Mason, je suppose que j'aurais dû enquêter un peu plus avant de demander ... Quoi qu'il en soit; Je me sens plutôt paresseux ces derniers temps, et TList et/ou TObjectList est plus pratique donc je vais faire un tour. :) +1 – conciliator
J'ai juste besoin de la même chose et ça marche bien, mais je reçois une fuite de mémoire chaque fois que j'ajoute un nouvel élément. Quelques idées pour résoudre ce problème? –
Après un certain temps d'enquête, j'ai découvert que TValue.MakeWithoutCopy résout le problème de la fuite de mémoire. –