微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何将 TClass 转换为 T?

如何解决如何将 TClass 转换为 T?

我使用 RTTI (SuperObject) 将 JSON 转换为对象:

class function RecordJson.Json2Record<T>(const obj: ISuperObject): T;
var
  ctx: TSuperRttiContext;
begin
  ctx := TSuperRttiContext.Create;
  try
    Result := ctx.AsType<T>(obj);
  finally
    ctx.Free;
  end;
end;

我使用这种方式并且有效:

if aSo.o['tdistanceBhTopConv'] <> nil then
  Result := RecordJson.Json2Record<tdistanceBhTopConv>(aSo.o['tdistanceBhTopConv']);

但是我有很多课程。所以我创建了一个TDictionary来记录字符串和类的关系,现在我想使用以下代码

FClassDic: TDictionary<string,TClass>;
FClassDic.Add('tdistanceValTopConv',tdistanceValTopConv);
FClassDic.Add('tdistanceBhTopConv',tdistanceBhTopConv);
FClassDic.Add('TLbXsConv',TLbXsConv);
FClassDic.Add('TConcreteConv',TConcreteConv);
for Key in FClassDic.Keys do
  if aSo.o[Key] <> nil then
  begin
    Result := RecordJson.Json2Record<FClassDic.Items[Key]>(aSo.o[Key]);
  end;

但它无法编译:

E2250 没有可以使用这些参数调用的“Json2Record”的重载版本

我知道这是因为 TClass(实例类)和 T(实例)的不同。

有什么办法可以解决这个问题吗?

解决方法

您可以尝试使用对象创建过程创建字典,但如果真的值得...

type
  // Object construction function type
  TCreateObjectProc = reference to function(const ctx: TSuperRttiContext; obj: ISuperObject): TObject;

  // Dictionary specification
  FCreateDict: TDictionary<string,TCreateObjectProc>;

然后用对象构造函数填充字典

  // Dictionary initialisation
  FCreateDict.Add('TDistanceValTopConv',function(const ctx: TSuperRttiContext; obj: ISuperObject): TObject
    begin
      Result := ctx.AsType<TDistanceValTopConv>(obj);
    end);

  FCreateDict.Add('TDistanceBhTopConv',function(const ctx: TSuperRttiContext; obj: ISuperObject): TObject
    begin
      Result := ctx.AsType<TDistanceBhTopConv>(obj);
    end);

  FCreateDict.Add('TLbXsConv',function(const ctx: TSuperRttiContext; obj: ISuperObject): TObject
    begin
      Result := ctx.AsType<TLbXsConv>(obj);
    end);

  FCreateDict.Add('TConcreteConv',function(const ctx: TSuperRttiContext; obj: ISuperObject): TObject
    begin
      Result := ctx.AsType<TConcreteConv>(obj);
    end);

然后使用它

  for Key in FCreateDict.Keys do
    if aSo.o[Key] <> nil then
    begin
      ctx := TSuperRttiContext.Create;
      try
        Result := FCreateDict.Items[Key](ctx,aSo.o[Key]);
      finally
        ctx.Free;
      end;
    end;

当使用 Remy 的 TSerializer<T: class> 类时:

type
  TSerializer<T: class> = class
  public
    class function Deserialize(const ctx: TSuperRttiContext; obj: ISuperObject): TObject;
  end;

class function TSerializer<T>.Deserialize(const ctx: TSuperRttiContext;
  obj: ISuperObject): TObject;
begin
  Result := ctx.AsType<T>(obj);
end;

那么关于字典初始化的代码如下(使用Delphi 10.3编译)

  FCreateDict.Add('TDistanceValTopConv',TSerializer<TDistanceValTopConv>.Deserialize);
  FCreateDict.Add('TDistanceBhTopConv',TSerializer<TDistanceBhTopConv>.Deserialize);
  FCreateDict.Add('TLbXsConv',TSerializer<TLbXsConv>.Deserialize);
  FCreateDict.Add('TConcreteConv',TSerializer<TConcreteConv>.Deserialize);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。