how to set array length at runtime? SetLength (t.GetProperty ('Propertys'), 3); ????
unit Unit3; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TSubProperty = Class private Fitem2: Integer; Fitem1: String; procedure Setitem1(const Value: String); procedure Setitem2(const Value: Integer); published property item1:String read Fitem1 write Setitem1; property item2:Integer read Fitem2 write Setitem2; End; TArraySubPropertys=array of TSubProperty; TmyObject = Class private FPropertys: TArraySubPropertys; procedure SetPropertys(const Value: TArraySubPropertys); published property Propertys:TArraySubPropertys read FPropertys write SetPropertys; End; TForm3 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form3: TForm3; implementation {$R *.dfm} procedure TForm3.Button1Click(Sender: TObject); var myObject:TmyObject; ctx : TRttiContext; t : TRttiType; obj:TObject; begin myObject :=TmyObject.Create; ctx := TRttiContext.Create; t := ctx.GetType(myObject.ClassType); // setLength(t.GetProperty('Propertys'),3); ???????????????????????????????????? obj:= (t.GetProperty('Propertys').PropertyType as TRttiDynamicArrayType).ElementType.AsInstance.MetaclassType.Create; //showmessage(obj.toStirng); --> TSubProperty t.GetProperty('Propertys').getValue(myObject).setArrayElement(0,obj); obj:= (t.GetProperty('Propertys').PropertyType as TRttiDynamicArrayType).ElementType.AsInstance.MetaclassType.Create; t.GetProperty('Propertys').getValue(myObject).setArrayElement(1,obj); obj:= (t.GetProperty('Propertys').PropertyType as TRttiDynamicArrayType).ElementType.AsInstance.MetaclassType.Create; t.GetProperty('Propertys').getValue(myObject).setArrayElement(2,obj); { myObject.Propertys[0] :=TSubProperty.Create; myObject.Propertys[0].item1 :='x'; myObject.Propertys[0].item2 :=1; myObject.Propertys[1] :=TSubProperty.Create; myObject.Propertys[1].item1 :='y'; myObject.Propertys[1].item2 :=2; myObject.Propertys[2] :=TSubProperty.Create; myObject.Propertys[2].item1 :='z'; myObject.Propertys[2].item2 :=3; ShowMessage(myObject.Propertys[2].item1); FreeAndNil(myObject.Propertys[2]); FreeAndNil(myObject.Propertys[1]); FreeAndNil(myObject.Propertys[0]); } FreeAndNil(myObject); end; { TSubProperty } procedure TSubProperty.Setitem1(const Value: String); begin Fitem1 := Value; end; procedure TSubProperty.Setitem2(const Value: Integer); begin Fitem2 := Value; end; { TmyObject } procedure TmyObject.SetPropertys(const Value: TArraySubPropertys); begin FPropertys := Value; end; end.
EDIT:
This code changes the length of the array, but incorrectly. It is a random value instead of 5. (19736192)
procedure TForm3.Button3Click(Sender: TObject); var myObject:TmyObject; ctx : TRttiContext; t : TRttiType; v:TValue; len:Longint; p:pointer; begin myObject :=TmyObject.Create; ctx := TRttiContext.Create; t := ctx.GetType(myObject.ClassType); V := t.GetField('FPropertys').GetValue(myObject); len:=5; p:=v.GetReferenceToRawData; ShowMessage(inttostr(integer(@myObject.FPropertys))); //19795652 ShowMessage(inttostr(integer(p))); //19795672 DynArraySetLength(p,v.TypeInfo,1,@len); t.GetField('FPropertys').SetValue(myObject,v); ShowMessage(inttostr(length(myObject.Propertys))); //array length=19736192 ??? end;
EDIT 2:
@Robert Love, thanks for the answer, but the problem continues. (Embarcadero® Delphi® 2010 Version 14.0.3513.24210)
press 2 wrong pointer operation.
procedure TForm7.Button2Click(Sender: TObject); var myObject:TmyObject; ctx : TRttiContext; t : TRttiType; v : Tvalue; p : Pointer; Len : Longint; begin myObject :=TmyObject.Create; ctx := TRttiContext.Create; t := ctx.GetType(myobject.ClassType); V := t.GetProperty('Propertys'); Len := 3; P := V.GetReferenceToRawData; DynArraySetLength(P,V.TypeInfo,1,@Len); // error invalid pointer operation ShowMessage(inttostr(length(myObject.Propertys))); end;