Delphi 如何将TRTTIInstanceType obj引用转换为其实际对象引用?
我正在尝试使用扩展的RTTI功能,这就是我坚持的地方Delphi 如何将TRTTIInstanceType obj引用转换为其实际对象引用?,delphi,Delphi,我正在尝试使用扩展的RTTI功能,这就是我坚持的地方 t := (c.FindType('Classes.TStringList') as TRttiInstanceType); SL := t.GetMethod('Create').Invoke(t.MetaclassType,[]); t.GetMethod('Add').Invoke(SL,['Hello Do you like my hat?']); Lines := t.GetProperty('Text').GetValue(SL.
t := (c.FindType('Classes.TStringList') as TRttiInstanceType);
SL := t.GetMethod('Create').Invoke(t.MetaclassType,[]);
t.GetMethod('Add').Invoke(SL,['Hello Do you like my hat?']);
Lines := t.GetProperty('Text').GetValue(SL.AsObject);
直到现在它还可以正常工作
现在我想改变这个值
Lines := 'Test';
t.GetProperty('Text').SetValue(**?**,Lines);
在这里,我应该给出TRTTIinstancetype引用还是实际对象引用。
如果实际对象引用,我将如何给出它
TestStringList := t(**how will i get the actual object from this TRTTIinstancetype**).
首先,如果您打算在所有这些任务中使用Rtti,我将回答应该如何正确完成,但在这种情况下可以避免使用Rtti。例如: 由于您正在使用此行创建stringlist:
SL := t.GetMethod('Create').Invoke(t.MetaclassType,[]);
以后可以将其用作TStringlist,无需使用Rtti:
var
SL: TStringList;
...
begin
...
SL := (t.GetMethod('Create').Invoke(t.MetaclassType,[]).ASObject) as TStringList;
所以你可以打电话:
SL.Text := Lines;
而不是:
t.GetProperty('Text').SetValue(SL.AsObject,Lines);
但是,如果您想将Rtti用于所有这些任务,您不应该这样做:
SL := t.GetMethod('Create').Invoke(t.MetaclassType,[]);
如果方法Create不是构造函数呢?对于TStringList来说是可以的,但是对于其他类型来说可能会失败。最好使用单独的函数来使用Rtti创建对象,或者使用普通TClass来完成此任务:
如果要调用不带参数的构造函数:
SL := t.MetaclassType.Create;
另一种选择:
function CreateType(AType: TRttiType): TObject;
var
AMethCreate: TRttiMethod;
instanceType: TRttiInstanceType;
begin
if AType.IsInstance then
begin
for AMethCreate in AType.GetMethods do
begin
if (AMethCreate.IsConstructor) and (Length(AMethCreate.GetParameters) = 0) then
begin
instanceType := AType.AsInstance;
Result := AMethCreate.Invoke(instanceType.MetaclassType, []).AsObject;
Exit;
end;
end;
end;
Result := nil;
end;
SetValue
的Instance
参数与GetValue
的Instance
参数完全相同。因此,您只需准确地传递调用GetValue
时已经完成的操作。即SL.AsObject
:
t.GetProperty('Text').SetValue(SL.AsObject, Lines);
关于问题的最后一部分,如果您需要将
SL
转换为具有特定类的对象,在本例中,TStringList
,则可以使用运行时强制转换:
MyStringList := SL.AsObject as TStringList;
然而,这样做意味着您首先不需要使用RTTI。使用我回答的第一部分中的方法是RTTI方法来完成你的要求。这听起来合乎逻辑,但它是不正确的。此代码不可编译。SL是一个
t值
。但是SetValue
实例参数是一个指针
。请参阅我的答案以了解正确的方法。@DavidHeffernan如果SL被声明为TStringList,则是正确的。很明显,SL是TValue。很抱歉,这个答案不正确。我看不出有任何理由保留它。这是误导。现在你没有回答被问到的问题。通常,当使用Rtti时,不知道对象是什么类型。因此,不可能在编译时确定类型。我真的不知道你在这里想干什么。我正确地回答了这个问题。答案很简单。现在是展现优雅的时候了。首先,当你的答案完全不同时,你会获得一张赞成票。既然你知道一个错误的、不同的答案获得了向上投票权,你应该删除那个有虚假向上投票权的答案,然后重新开始。@DavidHeffernan我只是想帮你。如果可以避免使用Rtti,那么我认为应该这样做。我将很快编辑我的答案。谢谢David Heffernan&Linas
t.GetProperty('Text').SetValue(SL.AsObject, Lines);
MyStringList := SL.AsObject as TStringList;