PiedSoftware 4 Posted yesterday at 05:43 AM Hi It seems like a natural thing to want: is there a way to get all the datasouces that have dataset = ADataset? Other than looping through the components property of the owner of course. I was looking at the code of TDataset. It even has a private member variable FDatasources: TList<TDatasource>, but it is not exposed. So close! TIA Mark 1 Share this post Link to post
Patrick PREMARTIN 121 Posted yesterday at 11:00 AM (edited) Perhaps you can try to access it from a helper on TDataSet... Edited yesterday at 11:00 AM by Patrick PREMARTIN Share this post Link to post
Remy Lebeau 1568 Posted yesterday at 02:43 PM (edited) 3 hours ago, Patrick PREMARTIN said: Perhaps you can try to access it from a helper on TDataSet... Class helpers don't have access to private members anymore since Delphi 10.1 Berlin. https://blogs.embarcadero.com/closing-the-class-helpers-private-access-loophole/ Edited yesterday at 02:47 PM by Remy Lebeau 1 Share this post Link to post
Patrick PREMARTIN 121 Posted yesterday at 04:19 PM 1 hour ago, Remy Lebeau said: Class helpers don't have access to private members anymore since Delphi 10.1 Berlin. https://blogs.embarcadero.com/closing-the-class-helpers-private-access-loophole/ Ah, yes, I've forgotten that. So no other solution than RTTI or checking all components in loops. Mark, you're probably not the first one in 30 years to want to access it. Perhaps you can open a "new feature" request on https://qp.embarcadero.com asking for having DataSources[] (read only) and DataSourceCount public properties on TDataSet ? (and explain why you need them) Share this post Link to post
PiedSoftware 4 Posted 17 hours ago (edited) 15 hours ago, Patrick PREMARTIN said: Perhaps you can try to access it from a helper on TDataSet... I don't know if it has the right meaning though. And since in Delphi there can only be one helper, I would avoid that approach in case someone else had a better use for it. Edited 17 hours ago by PiedSoftware Share this post Link to post
Keesver 25 Posted 13 hours ago As a last resort you can define your own TDataset type with a public 'FDatasource' member and then cast the TDataset to this type. Design wise this is a clear 'hack' but it will do the job: unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Datasnap.DBClient, Vcl.StdCtrls, System.Generics.Collections; type TForm1 = class(TForm) ClientDataSet1: TClientDataSet; Button1: TButton; DataSource1: TDataSource; DataSource2: TDataSource; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; THackedDataSet = class(TComponent) public FFields: TFields; FAggFields: TFields; FFieldDefs: TFieldDefs; FFieldDefList: TFieldDefList; FFieldList: TFieldList; FDataSources: TList<TDataSource>; end; PHackedDataSet = ^THackedDataSet; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin var ds := PHackedDataSet(@ClientDataSet1)^; ShowMessage(ds.Name); for var src in ds.FDataSources do ShowMessage(src.Name); end; end. Share this post Link to post
Remy Lebeau 1568 Posted 3 hours ago (edited) 10 hours ago, Keesver said: As a last resort you can define your own TDataset type with a public 'FDatasource' member and then cast the TDataset to this type. Design wise this is a clear 'hack' but it will do the job That approach is dependent on the layout of the original class, and could break between updates, so use with caution. It is also not a last resort, either. A safer approach would be to use RTTI to get the offset of the desired class member, and then use pointer arithmetic to access the member, eg: uses ..., System.Rtti; private DataSourcesOffset: Integer; ... procedure TForm1.Form1Create(Sender: TObject); var Ctx: TRttiContext; begin DataSourcesOffset := Ctx.GetType(TClientDataSet).GetField('FDataSources').Offset; end; procedure TForm1.Button1Click(Sender: TObject); type PDataSourceList = ^TList<TDataSource>; begin var ds := PDataSourceList(PByte(ClientDataSet1) + DataSourcesOffset)^; for var src in ds do ShowMessage(src.Name); end; Edited 3 hours ago by Remy Lebeau Share this post Link to post