Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi-将TValue传递给泛型方法_Delphi_Rtti_Delphi 10.1 Berlin - Fatal编程技术网

Delphi-将TValue传递给泛型方法

Delphi-将TValue传递给泛型方法,delphi,rtti,delphi-10.1-berlin,Delphi,Rtti,Delphi 10.1 Berlin,我需要使用RTTI迭代一个具有复杂结构的类。这个类有几个记录成员,我也想迭代这些成员 TRTTIHelpers<T> = class public class function DoGetValuesForClass(aClassInst: T): TStringList; class function DoGetValuesForRecord(aRec: T): TStringList; end; TRTTIHelpers=class 公众的 类函数Do

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

 TRTTIHelpers<T> = class
  public
    class function DoGetValuesForClass(aClassInst: T): TStringList;
    class function DoGetValuesForRecord(aRec: T): TStringList;
  end;
TRTTIHelpers=class
公众的
类函数DoGetValuesForClass(aClassInst:T):TStringList;
类函数DoGetValuesForRecord(aRec:T):TStringList;
结束;
我知道当我班上有一个记录在案的成员时:

   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
rt.GetProperties()do中的prop的

开始
如果prop.PropertyType为TRttiRecordType,则
开始
左值:=属性GetValue(aInst);
Result.AddStrings(TRTTIHelpers.DoGetValuesForRecord(TValue)) 使用
TValue
的方法将值强制转换为
T

lValue := prop.GetValue(aInst);
Result.AddStrings(TRTTIHelpers<T>.DoGetValuesForRecord(lValue.AsType<T>));
lValue:=prop.GetValue(aInst);
AddStrings(TRTTIHelpers.DoGetValuesForRecord(lValue.AsType));
这个简单的程序演示了这一点:

{$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.
{$APPTYPE控制台}
使用
System.RTTI;
类型
TMyRecord=记录
foo:整数;
结束;
TMyClass=类
函数GetRec:TMyRecord;
财产记录:TMyRecord read GetRec;
函数GetInt:Integer;
属性Int:整数读取GetInt;
结束;
函数TMyClass.GetRec:TMyRecord;
开始
Result.foo:=42;
结束;
函数TMyClass.GetInt:Integer;
开始
结果:=666;
结束;
主程序;
变量
研究所:TMyClass;
ctx:trtti上下文;
类型:trtti型;
财产:信托财产;
价值:TValue;
记录:TMyRecord;
开始
inst:=TMyClass.Create;
typ:=ctx.GetType(TypeInfo(TMyClass));
对于typ.GetProperties中的prop,请不要开始
如果prop.Name='Rec',则开始
值:=属性获取值(inst);
rec:=value.AsType;
书面文件(rec.foo);
结束;
结束;
结束;
开始
尝试
主要的;
除了
关于E:Exception-do
Writeln(E.ClassName,“:”,E.Message);
结束;
Readln;
结束。
当然,这确实需要属性
prop
的类型正确。如果没有,那么您将遇到运行时错误。在上面的示例中,我通过测试属性的名称来确保获得所需的属性,从而确保这一点。如果删除该测试,则程序将失败,并出现运行时
EInvalidCast
错误

看看你的代码,我怀疑你很可能会遇到这样的错误。如果
rt
的每个属性都是相同的类型,我会感到惊讶


查看
TRTTIHelpers
我认为它目前的形式对您没有多大帮助。至少,您知道它不会与基于RTTI的代码很好地交互。原因是对
TRTTIHelpers
的调用要求您在编译时提供类型参数。但对于RTTI代码,您在编译时不知道该类型。我怀疑
TRTTIHelpers
可能不应该是一个泛型类,而是使用RTTI类型为您提供灵活的运行时确定类型的功能。这个建议当然可能是错误的,但我只有问题中的一小部分代码来指导我。

好吧,这就是你所问问题的答案。运行时错误告诉您,
lValue
中的内容不是类型
T
。lValue中的内容是类型TRTTIRecordType-如果prop.PropertyType是TRTTIRecordType,那么-我的类中有一个记录类型Yes,一个记录类型。但是,正如运行时错误告诉您的那样,不一定与泛型
T
的类型相同。我的代码基本上与您发布的代码相同,只是我希望从行值传递值:=prop.GetValue(inst);作为另一个函数的泛型类型。这可能吗?我答案中的代码证明它是正确的。你的错误肯定是一个基本的理解,如果你不理解,你就不会取得进步。不要想象一些神奇的代码块会解开你的枷锁。您认为
lValue
包含类型为
T
的记录,但系统告诉您它没有。信任这个系统。您询问如何从
TValue
中提取特定类型的值,我的回答清楚地说明了这一点。现在由您来调试您的程序。