Delphi 如何将TRTTIInstanceType obj引用转换为其实际对象引用?

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.

我正在尝试使用扩展的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**).

首先,如果您打算在所有这些任务中使用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;