Delphi - 将TValue传递给泛型方法

时间:2017-03-16 15:34:55

标签: delphi rtti delphi-10.1-berlin

我需要使用RTTI遍历具有复杂结构的类。该类有几个记录成员,我也想迭代。

 TRTTIHelpers<T> = class
  public
    class function DoGetValuesForClass(aClassInst: T): TStringList;
    class function DoGetValuesForRecord(aRec: T): TStringList;
  end;

我知道当我在课堂上有一个成员时,这是一个记录:

   for prop in rt.GetProperties() do
    begin
      if prop.PropertyType is TRttiRecordType then
      begin
        lValue := prop.GetValue(aInst);
        Result.AddStrings(TRTTIHelpers<T>.DoGetValuesForRecord(TValue)); <--
      end

如何将TValue作为参数传递给DoGetValuesForRecord,以便我也可以遍历记录?

1 个答案:

答案 0 :(得分:7)

使用TValue的{​​{3}}方法将值转换为T

lValue := prop.GetValue(aInst);
Result.AddStrings(TRTTIHelpers<T>.DoGetValuesForRecord(lValue.AsType<T>));

这个简单的程序证明了这一点:

{$APPTYPE CONSOLE}

uses
  System.RTTI;

type
  TMyRecord = record
    foo: Integer;
  end;

  TMyClass = class
    function GetRec: TMyRecord;
    property Rec: TMyRecord read GetRec;
    function GetInt: Integer;
    property Int: Integer read GetInt;
  end;

function TMyClass.GetRec: TMyRecord;
begin
  Result.foo := 42;
end;

function TMyClass.GetInt: Integer;
begin
  Result := 666;
end;

procedure Main;
var
  inst: TMyClass;
  ctx: TRttiContext;
  typ: TRttiType;
  prop: TRttiProperty;
  value: TValue;
  rec: TMyRecord;
begin
  inst := TMyClass.Create;
  typ := ctx.GetType(TypeInfo(TMyClass));
  for prop in typ.GetProperties do begin
    if prop.Name='Rec' then begin
      value := prop.GetValue(inst);
      rec := value.AsType<TMyRecord>;
      Writeln(rec.foo);
    end;
  end;
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

当然,这确实要求属性prop的类型正确。如果没有,那么您将遇到运行时错误。在上面的例子中,我确保通过测试属性的名称来确保获得所需的属性。如果删除该测试,则程序将失败,并显示运行时EInvalidCast错误。

查看您的代码我怀疑您很可能会遇到此类错误。如果rt的每个属性属于同一类型,我会感到惊讶。

TRTTIHelpers<T>我不认为它对你目前的状态非常有用。至少,它不会与基于RTTI的代码很好地交互。原因是调用TRTTIHelpers<T>需要您在编译时提供type参数。但是使用RTTI代码,您在编译时就不知道该类型。我怀疑TRTTIHelpers<T>可能不应该是泛型类,而是使用RTTI类型为您提供灵活的运行时确定类型的功能。这个建议当然可能是错误的,但我只是在问题中有一小段代码来指导我。