目前我有很多关于这样的辅助方法的记录:
TRec1 = packed record
S1: string;
S2: string;
procedure FromJSON(const AJSON: string);
function ToJSON: string;
end;
procedure TRec1.FromJSON(const AJSON: string);
begin
RecordLoadJSON(Self, StringToUTF8(AJSON), TypeInfo(TRec1));
end;
function TRec1.ToJSON: string;
begin
Result := UTF8ToString(RecordSaveJSON(Self, TypeInfo(TRec1)));
end;
TRec2 = packed record
S1: string;
I1: string;
procedure FromJSON(const AJSON: string);
function ToJSON: string;
end;
procedure TRec2.FromJSON(const AJSON: string);
begin
RecordLoadJSON(Self, StringToUTF8(AJSON), TypeInfo(TRec2));
end;
function TRec2.ToJSON: string;
begin
Result := UTF8ToString(RecordSaveJSON(Self, TypeInfo(TRec2)));
end;
如您所见,所有记录都包含相同的ToJSON和FromJSON方法。 除TypeInfo()
外,此方法包含完全相同的代码任何使用泛型的方法,不要为每条记录分析这种方法吗?
答案 0 :(得分:1)
记录或课程?
尽管Delphi支持方法,但记录仍然是二等公民,因为没有记录继承的支持
类具有记录的所有功能以及完整的OOP功能集,因此它们通常是更好的选择。但是,您需要处理需要在非ARC平台上手动管理类的创建和销毁的引用语义,以及具有自动清理的记录的无关值语义。
非泛型解决方案(使用课程)
将字符串容器声明为类并使用继承。
TRec1 = class(TPersistent)
S1: string;
S2: string;
procedure FromJSON(const AJSON: string);
function ToJSON: string;
end;
TRec2 = class(TRec1)
end;
procedure TRec1.FromJSON(const AJSON: string);
begin
RecordLoadJSON(Self, StringToUTF8(AJSON), Self.ClassInfo);
end;
function TRec1.ToJSON: string;
begin
Result := UTF8ToString(RecordSaveJSON(Self, Self.ClassInfo));
end;
从TPersistent
继承的所有类都有RTTI,因此self.classinfo
有效。
您可能需要根据需要修改RecordSaveJSON
来电。
泛型解决方案
如果为单元{$M+}
启用了RTTI并且必须使用记录,则只需使用记录之外的方法并将记录类型作为通用参数提供。
TRec1 = record
data: typex;
....
end;
TDoJSONThings = record //helper record for any and all types with RTTI.
procedure FromJSON<T:record>(var Data: T; const JSON: string); static;
function ToJSON<T:record>(const [ref] Data: T): string; static;
end;
procedure TDOJSONThings.FromJSON<T>(var Data: T; const JSON: string); static;
var
pt: PTypeInfo;
begin
pt:= TypeInfo(T);
RecordLoadJSON(Data, StringToUTF8(AJSON), pt);
end;
function TDOJSONThings.ToJSON<T:record>(const [ref] Data: T): string; static;
var
pt: PTypeInfo;
begin
pt:= TypeInfo(T);
Result:= UTF8ToString(RecordSaveJSON(Data, pt));
end;
<强>说明强>
使用record helper
(如在THelper = record helper for TRec1
中)将不起作用,因为这只适用于TRec1
,并且记录遗憾地不支持继承。
使用独立方法会更好,但Delphi不允许不属于记录或类的泛型方法。
哦,请放弃1970年代的packed record
风格构造。它没有任何意义,只是通过错位使代码变慢。