如何使用TypInfo RTTI方法为子属性项设置值?

3
在我的问题中:如何同时为多个类使用“Sender”参数和“As”操作符

我选择了Remy Lebeau的答案,因为它是最适合这种情况的最动态的技术。它使用了RTTI TypInfo类。
但是当我使用这个类时,又遇到了另一个问题:如何设置子属性值?
function TRemote.UpdateQuery(DataSet: TDataSet; SQL: String): Boolean;
var
  PropInfo: PPropInfo;
begin
{ atualiza o código SQL padrão de um dataSet de consulta tipo View }
  PropInfo := GetPropInfo(DataSet, 'SQL', []);
  if not Assigned(PropInfo) then
  begin
    Result := False;
    Exit;
  end;
  try
    DataSet.Close;
    SetPropValue(DataSet, PropInfo, SQL);
    DataSet.Open;
    Result := True;
  except
    Result := False;
  end;
end;

例子: 我有一个TIBQuery,我想要更新SQL属性的文本。 但是SQL属性是一个TStrings类,所以我必须使用SQL.Text。 在上面的代码中,它会引发一个“无效的属性类型”错误,因为我得到了一个TStrings,后来我尝试设置一个普通的字符串。
如何使用GetPropInfo访问SQL.Text? 是否有一个TIBQuery和TZQuery的共同祖先,它具有SQL属性,这样我就可以改变函数参数中的TDataSet?

你不能只是创建一个本地字符串列表,SQLstrings := TStringList.Create,然后执行 SQLstrings.Text := SQL,最后将 SQLstrings 传递给 SetPropValue 吗? - David Heffernan
2
你可以使用 TStrings(GetObjectProp(DataSet, 'SQL')) 来获取 SQL 实例。你确定需要使用 GetPropInfo 吗?这将是一段难以阅读的代码。 - TLama
如果使用String而不是PPropInfo请求属性,如果找不到该属性,则会引发异常。 - Remy Lebeau
@DavidHeffernan 我已经尝试过了,但编译器说我们不能在 SetPropValue 中使用 TStrings。 - NaN
1
你需要使用 SetObjectProp()SetPropValue() 不支持对象。 - Remy Lebeau
1个回答

9

TStrings.Text 属性在 Delphi 2006 中无法通过 RTTI 访问。即使可以访问,您也不需要使用 RTTI 来访问它。由于您知道 SQL 属性是一个 TStrings 对象,因此可以直接从该属性中检索实际对象指针并将其强制转换为 TStrings 指针,然后可以对该对象执行所需操作,例如:

function TRemote.UpdateQuery(DataSet: TDataSet; SQL: String): Boolean; 
var 
  PropInfo: PPropInfo; 
  SQLObj: TStrings;
begin 
  Result := False; 
  try 
    PropInfo := GetPropInfo(DataSet, 'SQL', [tkClass]); 
    if not Assigned(PropInfo) then Exit; 
    SQLObj := TStrings(GetObjectProp(DataSet, PropInfo, TStrings));
    if not Assigned(SQLObj) then Exit; 
    DataSet.Close; 
    SQLObj.Text := SQL; 
    DataSet.Open; 
    Result := True; 
  except 
  end; 
end; 

2
+1;@EASI,我知道你特别提出了这个问题,但是你可以直接使用GetObjectProp。在使用GetObjectProp之前使用GetPropInfo没有任何优势(因为它在另一个GetObjectProp重载中被调用)。 - TLama
2
在调用GetObjectProp()之前调用GetPropInfo()可以避免在未找到属性时引发异常。另一个重载版本的GetObjectProp()不提供该选项,它会引发异常。我想在这种情况下由于try/except是可以接受的,但通常情况下,如果您可以避免异常,就可以避免与之相关的开销。 - Remy Lebeau
太棒了。我完全忘记了查看 GetObjectProp。这非常有教育意义! - NaN
我没有找到TIBQueryTZQuery(来自ZeosLib)的共同祖先,但我记得使用Params属性。因此,我根本不需要使用SQL属性。我只需要在正确的位置设置:Parameters,然后通过DS.ParamByName('ActivityType').AsString := ...更改其内容。 - NaN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接