如何使用delphi 2010 rtti设置数组长度 [英] how to set array length with delphi 2010 rtti

查看:151
本文介绍了如何使用delphi 2010 rtti设置数组长度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在运行时设置数组长度?
setLength(t.GetProperty(‘Propertys’),3);

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.

编辑:

此代码更改了数组的长度,但是错误。
是一个随机值,而不是5。(19736192)

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;

编辑2:

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

@Robert Love, thank you for reply but problem continues. (Embarcadero® Delphi® 2010 Version 14.0.3513.24210 )

单击button2
无效的指针操作。

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;


推荐答案

您可以使用DynArraySetLength函数。

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;

我在 RttiUtils.pas

这篇关于如何使用delphi 2010 rtti设置数组长度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆