3

In my Question: How to use “Sender” parameter with “As” operator for more then one class at a time

I choose the Remy Lebeau's Answer because it was the most dynamic tech for most situations like that. It uses the RTTI TypInfo Class.

But as I was using this class, another problem came: How do we Set a sub-property value?

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;

Example: I have a TIBQuery and I want to update the text of the SQL property. But the SQL property is a TStrings class, so I have to use SQL.Text. In the code above, It will raise an error "Invalid Property Type" because I got a TStrings and later I try to Set a normal String.

How to reach the SQL.Text using GetPropInfo? Is there a common ancestor of TIBQuery and TZQuery that has the SQL property, so I can change to, instead of the TDataSet in the function parameter?

Community
  • 1
  • 1
NaN
  • 8,596
  • 20
  • 79
  • 153
  • Can't you just create a local string list, `SQLstrings := TStringList.Create`, then do `SQLstrings.Text := SQL`, and finally pass `SQLstrings` to `SetPropValue`? – David Heffernan Jul 30 '12 at 19:30
  • 2
    The `SQL` instance you can get simply with `TStrings(GetObjectProp(DataSet, 'SQL'))`. Are you sure you need to use the `GetPropInfo` ? It will be *unreadable* piece of code. – TLama Jul 30 '12 at 19:36
  • Requesting a property by `String` instead of by `PPropInfo` will raise an exception if the property cannot be found. – Remy Lebeau Jul 30 '12 at 20:19
  • @DavidHeffernan I've tried, but the compiler says that we can't use TStrings with SetPropValue. – NaN Jul 30 '12 at 21:06
  • 1
    You need to use `SetObjectProp()` instead. `SetPropValue()` does not supports objects. – Remy Lebeau Jul 30 '12 at 22:20

1 Answers1

9

The TStrings.Text property is not accessible via RTTI in Delphi 2006. Even if it were, you do not need to use RTTI to access it anyway. Since you know the SQL property is a TStrings object, you can simply retreive the actual object pointer from the property and type-cast it to a TStrings pointer, then you can do whatever you need to do with that object, eg:

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; 
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 2
    +1; @EASI, I know you've asked this specifically, but you can use directly `GetObjectProp`. There's no advantage of using `GetPropInfo` before (it is called inside of the other `GetObjectProp` overload). – TLama Jul 30 '12 at 19:52
  • 2
    Calling `GetPropInfo()` before `GetObjectProp()` allows you to avoid an exception being raised if the property is not found. The other overloaded version of `GetObjectProp()` does not give you that option, it will raise an exception. Which I guess is OK in this case due to the `try/except`, but in general, if you can avoid an exception, you avoid the overhead that goes with it. – Remy Lebeau Jul 30 '12 at 20:17
  • This is great. I've completely forgot to see `GetObjectProp`. This is very educative! – NaN Jul 30 '12 at 21:10
  • I did not found the common Ancestor for `TIBQuery` and `TZQuery` (from ZeosLib) but I remembered to use the `Params` property. So I don't need to use SQL property at all. I just need to set the :Parameters in the correct place and them alter it's contents by `DS.ParamByName('ActivityType').AsString := ...` – NaN Jul 30 '12 at 21:12