使用的TValue
的AsType<T>
方法将值转换为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>
需要您在编译时提供类型参数。但是对于RTTI代码,在编译时你不知道这种类型。我怀疑TRTTIHelpers<T>
应该不是泛型类,而是使用RTTI类型为您提供功能,这对于运行时确定的键入来说是灵活的。这个建议当然可能是错误的,但是我只有这个问题中的一小段代码来指导我。
嗯,这是你问的问题的答案。运行时错误告诉你,无论'lValue'是什么,都不是'T'类型。 –
lValue中的内容是TRTTIRecordType类型 - 如果prop.PropertyType是TRttiRecordType,那么 - 并且我在我的类中有记录类型 – RBA
是,记录类型。但不一定与通用'T'类型相同,因为运行时错误会通知您。 –