如果您使列表属性
published
并删除对的调用
TFiler.DefineProperty()
,一切正常,如预期:
TTest = class(TComponent)
private
fList: TStringList;
procedure SetList(Value: TStringList);
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
property list: TStringList read fList;
published
property the_list_id_liketosave_without_publising: TStringList read fList write SetList;
end;
以下是其DFM二进制数据的外观:
54 50 46 30 05 54 54 65 73 74 00 30 74 68 65 5F : TPF0.TTest.0the_
6C 69 73 74 5F 69 64 5F 6C 69 6B 65 74 6F 73 61 : list_id_liketosa
76 65 5F 77 69 74 68 6F 75 74 5F 70 75 62 6C 69 : ve_without_publi
73 69 6E 67 2E 53 74 72 69 6E 67 73 01 06 06 61 : sing.Strings...a
71 77 7A 73 78 06 06 65 64 63 72 66 76 00 00 00 : qwzsx..edcrfv...
下面是文本输出:
object TTest
the_list_id_liketosave_without_publising.Strings = (
'aqwzsx'
'edcrfv')
end
如您所见,属性名称只有一个字符串:
the_list_id_liketosave_without_publising.Strings
在内部,
TStream.ReadComponent()
读取该字符串并在
.
字符,使用RTTI解析
the_list_id_liketosave_without_publising
根据实际情况
TStringList
对象,然后调用
DefineProperties('Strings')
在该对象上,让它流式传输其字符串列表数据,一切都很好。
ObjectBinaryToText()
做不了那么多工作。事实上,在查看RTL源代码后,发现
对象BinaryToText()
(至少在Delphi,但我确信FreePascal也是如此)
没有
支持自定义流媒体
TComponent.DefineProperties()
根本不需要
DefineProperties()
)!. 这是你问题的根源。
对象BinaryToText()
未实现完全流式传输系统
ReadComponent()
实现,只是它的一个子集。
然而,在这种情况下,一切都很好,因为
T字符串列表
以易于使用的简单格式写入自定义流数据
对象BinaryToText()
以进行处理。
什么时候
对象BinaryToText()
读取属性名称字符串,它按原样将其写入,而不以任何方式解析它,然后读取下一个字节并相应地处理它。
T字符串列表
使用以下格式:
vaList (TWriter.WriteListBegin())
vaString for each string (TWriter.WriteString())
vaNull (TWriter.WriteListEnd())
对象BinaryToText()
识别这些标记,因此当它遇到
vaList
(十六进制
01
)它需要在循环中读取值,直到读取
vaNull
(十六进制
00
),它知道如何阅读
vaString
(十六进制
06
)值。因此,写下
Strings
数据转换为输出文本。
在您的情况下
TTest
自定义流,它创建的DFM二进制数据有点不同:
54 50 46 30 05 54 54 65 73 74 00 28 74 68 65 5F : TPF0.TTest.(the_
6C 69 73 74 5F 69 64 5F 6C 69 6B 65 74 6F 73 61 : list_id_liketosa
76 65 5F 77 69 74 68 6F 75 74 5F 70 75 62 6C 69 : ve_without_publi
73 69 6E 67 01 07 53 74 72 69 6E 67 73 01 06 06 : sing..Strings...
61 71 77 7A 73 78 06 06 65 64 63 72 66 76 00 00 : aqwzsx..edcrfv..
00 00 : ..
如您所见,存在两个单独的属性名称字符串:
the_list_id_liketosave_without_publising
Strings
什么时候
对象BinaryToText()
读取
列表_喜欢保存而不发布
字符串,它假定它是完整的属性名,并读取下一个字节以确定要读取的属性的数据类型。该字节(十六进制
01
)被解释为
vaList(虚拟列表)
.下一个字节(十六进制
07
)被解释为
vaIdent
(又名
not vaNull
),因此它假设正在读取子属性的非空列表(实际上不是)。它试图读取
vaIdent公司
“属性”,其中下一个字节(十六进制
53
)被解释为缩进的字节长度(不是),然后它尝试读取那么多字节(十进制83)并失败。
为了使您
T测试
自定义流媒体可以正确使用
对象BinaryToText()
,您必须通过复制与
TStrings.DefineProperties()
实现(正如其流式方法
private
无法访问),例如:
TTest = class(TComponent)
private
fList: TStringList;
procedure ListFromReader(aReader: TReader);
procedure ListToWriter(aWriter: TWriter);
protected
procedure DefineProperties(aFiler: TFiler); override;
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
property list: TStringList read fList;
end;
procedure TTest.ListFromReader(aReader: TReader);
begin
aReader.ReadListBegin;
fList.BeginUpdate;
try
fList.Clear;
while not aReader.EndOfList do fList.Add(aReader.ReadString);
finally
fList.EndUpdate;
end;
aReader.ReadListEnd;
end;
procedure TTest.ListToWriter(aWriter: TWriter);
var
I: Integer;
begin
aWriter.WriteListBegin;
for I := 0 to fList.Count - 1 do aWriter.WriteString(fList[I]);
aWriter.WriteListEnd;
end;
procedure TTest.DefineProperties(aFiler: TFiler);
begin
inherited;
aFiler.DefineProperty('the_list_id_liketosave_without_publising', ListFromReader, ListToWriter, fList.Count > 0);
end;
constructor TTest.Create(aOwner: TComponent);
begin
inherited;
fList := TStringList.Create;
end;
destructor TTest.Destroy;
begin
fList.Free;
inherited;
end;
生成此DFM二进制数据的函数:
54 50 46 30 05 54 54 65 73 74 00 28 74 68 65 5F : TPF0.TTest.(the_
6C 69 73 74 5F 69 64 5F 6C 69 6B 65 74 6F 73 61 : list_id_liketosa
76 65 5F 77 69 74 68 6F 75 74 5F 70 75 62 6C 69 : ve_without_publi
73 69 6E 67 01 06 06 61 71 77 7A 73 78 06 06 65 : sing...aqwzsx..e
64 63 72 66 76 00 00 00 : dcrfv...
生成此输出文本的函数:
object TTest
the_list_id_liketosave_without_publising = (
'aqwzsx'
'edcrfv')
end
就是这样
对象BinaryToText()
它并不是像您试图实现的那样为通用自定义流媒体而设计的。它对它能(和不能)处理的事情非常专业。请记住,它主要设计用于IDE编辑器向用户显示DFM,因此它依赖于使用简单流格式的已发布组件。您尝试实现的内容超出了它的解析能力。
两个字节有什么区别?