delphi - 如何在动态数组的自定义类对象中使用 DefineProperties - Delphi

标签 delphi

我正在尝试创建自己的类对象并使用它来存储应用程序的各种数据类型,这在使用已发布属性时一切正常,我可以将它们流式传输到磁盘并毫无问题地返回。但我还需要流式传输一些动态整数类型数组。

            type
              TArrayOfInteger = array of integer;

              TSetting = class(TComponent)
              private
                fIntVal: integer;
                fIntArr: TArrayOfInteger;
                procedure ReadIntArr(Reader: TReader);
                procedure WriteIntArr(Writer: TWriter);
              protected
                procedure DefineProperties(Filer: TFiler); override;
              published
                property intval: integer read fIntVal write fIntVal;
                property intArr: TArrayOfInteger read fIntArr write fIntArr;
              end;

            { TSetting }

            procedure TSetting.DefineProperties(Filer: TFiler);
            begin
              inherited;
              Filer.DefineProperty('intArr', ReadIntArr, WriteIntArr, true);
            end;
            procedure TSetting.ReadIntArr(Reader: TReader);
            var
              i: integer;
              lvVal:Integer;
            begin
              i:=low(fintArr);
              Reader.ReadListBegin;
              {j := Reader.ReadInteger();
              setlength(fIntArr, j);
              for i := 0 to j - 1 do
              begin
                fIntArr[i] := Reader.ReadInteger();
              end;}
            while not Reader.EndOfList do begin
                fIntArr[i]:=Reader.ReadInteger;
                Inc(i);
              end;
              Reader.ReadListEnd;
            end;

            procedure TSetting.WriteIntArr(Writer: TWriter);
            var
              i: integer;
            begin
              Writer.WriteListBegin;
              //Writer.WriteInteger(integer(Length(fIntArr)));
              for i := Low(fIntArr) to High(fIntArr) do
              begin
                Writer.WriteInteger(fIntArr[i]);
              end;
              Writer.WriteListEnd;
            end;

            function ClassToStr(pvClass:TComponent):ansiString;
            var
              inStream, outStream: TMemoryStream;

            begin
              inStream := TMemoryStream.Create;
              outStream := TMemoryStream.Create;
              try
                inStream.WriteComponentRes(pvClass.ClassName, pvClass);
                //inStream.WriteComponent(pvClass);
                inStream.Position := 0;
               ObjectResourceToText(inStream, outStream);
               // ObjectBinaryToText(inStream,outStream);
                outStream.Position := 0;
                SetLength(Result,outStream.Size+1);
                FillChar(result[1],outStream.Size+1,0);
                outStream.ReadBuffer(result[1],outStream.Size);
              finally
                FreeAndNil(inStream);
                FreeAndNil(outStream);
              end;
            end;
            function StrToClass(pvStr:AnsiString;pvComponent:TComponent):tcomponent;
            var
              inStream, outStream: TMemoryStream;
            begin
              inStream := TMemoryStream.Create;
              outStream := TMemoryStream.Create;
              try
                if (pvStr<>'') then
                inStream.WriteBuffer(pvStr[1],length(pvStr));
                inStream.Position:=0;
                ObjectTextToResource(inStream, outStream);
               // ObjectTextToBinary(inStream,outStream);
                outStream.Position:=0;
                result:=outStream.ReadComponentRes(pvComponent); //*****Exception Fired*****
                //result:=outStream.ReadComponent(pvComponent);
              finally
                FreeAndNil(inStream);
                FreeAndNil(outStream);
              end;

            end;

            =============
            //test
            procedure TForm1.btn5Click(Sender: TObject);
            var
              lvObj,lv1: TSetting;
              lvStr:String;
              lvArr:TArrayOfInteger;
            begin
              lvObj := TSetting.Create(nil);
              try
                lvObj.intval := 12345;
                setlength(lvArr, 3);
                lvArr[0] := 222;
                lvArr[1] := 333;
                lvArr[2] := 444;
                lvObj.intArr:=lvArr;
                lvStr:=ClassToStr(lvObj);
                RegisterClass(TSetting);
                lvObj.intval:=1;
                lv1:=TSetting( StrToClass(lvStr,lvObj));
                if (lv1.intval>0) then
                mmo1.Text:=lvStr;
              finally
                FreeAndNil(lvObj);
              end;
              // WriteComponentResFile(ExtractFilePath(ParamStr(0))+ 'd.res',self);
            end;

            //First chance exception at $77925B68. Exception class EReadError with message 'Property  does not exist'. Process Project1.exe (23512)

            //First chance exception at $77925B68. Exception class EReadError with message 'Error reading TSetting.: Property  does not exist'. Process Project1.exe (23512)


result:=outStream.ReadComponentRes(pvComponent); //*****Exception Fired*****

最佳答案

读取数组时您没有分配该数组。你可以这样做:

procedure TSetting.ReadIntArr(Reader: TReader);
begin
  fIntArr := nil;
  Reader.ReadListBegin;
  while not Reader.EndOfList do begin
    SetLength(fIntArr, Length(fIntArr) + 1);
    fIntArr[high(fIntArr)] := Reader.ReadInteger;
  end;
  Reader.ReadListEnd;
end;

您需要进行的另一项更改是将 intArr 移至公共(public)属性。您不能在发布它的同时在 DefineProperties 中定义同名的属性。

我对您对 AnsiString 的使用有些怀疑。我希望在非 ASCII 字符的情况下使用 UTF-8 编码字节。也许您应该使用指定了适当编码的字符串流。

我个人对以这种方式使用表单流持怀疑态度。我更喜欢使用标准格式,例如 JSON。

关于delphi - 如何在动态数组的自定义类对象中使用 DefineProperties - Delphi,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36059349/

相关文章:

web-services - 使用 TidHTTPServer 以安全的方式处理 GET 请求

delphi - 更改 bsB 对角线宽度和间隙

delphi - 是否可以使用 TypeKind=tkMethod 为 TRttiType 创建 TRttiMethod 实例?

delphi - 为什么我应该使用 TCollections.CreateList<T> 而不是 TList<T>.Create

delphi - Delphi 2009 的设计模式

delphi - 将现有的 TLabels 插入到动态创建的 TLabels 数组中

delphi - 视觉形式继承 - Baseform 的变化

delphi - TVirtualStringTree - 设置列单元格/节点对齐

delphi - T 图表 - 不绘制小于 0 的值吗?

delphi - Delphi:二维数组到一维数组