我正在尝试使用extented 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.AsObject);
直到现在它正常工作 现在我想改变价值
Lines := 'Test';
t.GetProperty('Text').SetValue(**?**,Lines);
我应该在这里给出TRTTIinstancetype引用或实际对象引用。 如果实际对象参考我将如何给出。
TestStringList := t(**how will i get the actual object from this TRTTIinstancetype**).
答案 0 :(得分:3)
首先,如果您打算将Rtti用于所有这些任务,我将回答它应该如何正确完成,但在这种情况下,可以避免使用Rtti。 E.g:
由于您使用以下行创建了字符串列表:
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;
...
var
SL: TObject;
SL := CreateType(c.FindType('Classes.TStringList'));
...
t.GetProperty('Text').SetValue(SL,Lines);
答案 1 :(得分:3)
Instance
的{{1}}参数与SetValue
的{{1}}参数完全相同。因此,您只需要准确传递调用Instance
时已经执行的操作。即GetValue
:
GetValue
关于问题的最后部分,如果您需要将SL.AsObject
转换为具有特定类的对象,在这种情况下为t.GetProperty('Text').SetValue(SL.AsObject, Lines);
,那么您可以使用运行时强制转换:
SL
然而,这样做意味着您不需要首先使用RTTI。使用我的答案的第一部分中的方法是RTTI方式来做你想要的。