如何使用delphi 2010 rtti设置数组长度

发布于 2024-08-12 03:10:49 字数 4448 浏览 6 评论 0原文

如何在运行时设置数组长度? setLength(t.GetProperty('属性'),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.

编辑:

此代码更改了数组的长度,但错误。 是一个随机值而不是 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;

编辑 2:

@Robert Love,谢谢您的回复,但问题仍然存在。 (Embarcadero® Delphi® 2010 版本 14.0.3513.24210)

单击按钮2 无效的指针操作。

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;

how to set array length in 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 wrong.
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, thank you for reply but problem continues.
(Embarcadero® Delphi® 2010 Version 14.0.3513.24210 )

click button2
invalid 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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烂柯人 2024-08-19 03:10:49

您可以使用 DynArraySetLength 函数。

var
 ...
 V : TValue;
 Len : LongInt;
 P : Pointer;
begin
  ...
  V := t.GetProperty('Propertys');
  Len := 3;
  P := V.GetReferenceToRawData;
  DynArraySetLength(P,V.TypeInfo,1,@Len);
  ...
end;

我在 RttiUtils.pas 在 TArrayElementAdd 类中。

You can use the DynArraySetLength Function.

var
 ...
 V : TValue;
 Len : LongInt;
 P : Pointer;
begin
  ...
  V := t.GetProperty('Propertys');
  Len := 3;
  P := V.GetReferenceToRawData;
  DynArraySetLength(P,V.TypeInfo,1,@Len);
  ...
end;

I use this method in my RttiUtils.pas in the TArrayElementAdd class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文