记录的通用助手

时间:2017-03-11 07:59:45

标签: delphi generics helpers delphi-10.1-berlin

目前我有很多关于这样的辅助方法的记录:

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()

外,此方法包含完全相同的代码

任何使用泛型的方法,不要为每条记录分析这种方法吗?

1 个答案:

答案 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风格构造。它没有任何意义,只是通过错位使代码变慢。