Ian Branch 127 Posted May 3, 2023 Hi Team, I want to be able to make a generic function like this.. function SetDBSessionNames(const ComponentCount: Integer; const Components: TComponent; const sSessionName: string): boolean; begin // for var i := 0 to ComponentCount - 1 do begin // if (Components[i] is TEDBSession) then (Components[i] as TEDBSession).SessionName := sSessionName; // if (Components[i] is TEDBDatabase) then (Components[i] as TEDBDatabase).SessionName := sSessionName; // if (Components[i] is TnlhTable) then (Components[i] as TnlhTable).SessionName := sSessionName; // if (Components[i] is TnlhQuery) then (Components[i] as TnlhQuery).SessionName := sSessionName; // if (Components[i] is TnlhScript) then (Components[i] as TnlhScript).SessionName := sSessionName; // end; // end; That would be called like this.. // SetDBSessionNames(ComponentCount, Components, sSessionName); // The function is in a separate function library. Unfortunately it doesn't like "Components" in the if.... lines. 😞 I have obviously missed or misinterpreted some aspect. Some assistance/guidance would be appreciated. Regards & TIA, Ian Share this post Link to post
Keesver 23 Posted May 3, 2023 You are accessing variable 'Components' as if it where an array, but it is declared like a reference to a TComponent. I think you want to redeclare your function like: type TComponentArray = array of TComponent; function SetDBSessionNames(const ComponentCount: Integer; const Components: TComponentArray; const sSessionName: string): boolean; Share this post Link to post
Ian Branch 127 Posted May 3, 2023 Tks Keesver. That calms down the function itself, but now the calling function isn't happy What replaces Components in the calling function? SetDBSessionNames(ComponentCount, Components, sSessionName); Share this post Link to post
Renate Schaaf 64 Posted May 3, 2023 (edited) It looks like you want to use the component list of a TForm, so you should pass that form as a parameter: function SetDBSessionNames(const AForm: TForm; const sSessionName: string): boolean; begin // for var i := 0 to AForm.ComponentCount - 1 do begin // if AForm.Components[i] is TEDBSession then (AForm.Components[i] as TEDBSession).SessionName := sSessionName; .. Then you can call it in the code of a form as SetDBSessionNames(self, sSessionName); Edited May 3, 2023 by Renate Schaaf Share this post Link to post
Ian Branch 127 Posted May 3, 2023 (edited) Hi Renate, That looks like a winner but this.. SetDBSessionNames(Self, sSessionName); Gives me this in this case.. Quote [dcc32 Error] dmCurrent.pas(821): E2010 Incompatible types: 'TForm' and 'TdmC' In this case it is a Datamodule the function is being called from. Ian Edit: Solved - I made it an overload method and created one that use a TDataModule. Edited May 3, 2023 by Ian Branch Share this post Link to post
Uwe Raabe 2057 Posted May 3, 2023 Make it TComponent: function SetDBSessionNames(AContainer: TComponent; const sSessionName: string): boolean; begin // for var i := 0 to AContainer.ComponentCount - 1 do begin // var cmp := AContainer.Components[i]; if cmp is TEDBSession then TEDBSession(cmp).SessionName := sSessionName; ... Share this post Link to post
Ian Branch 127 Posted May 3, 2023 (edited) 2 minutes ago, Uwe Raabe said: Make it TComponent: Now we're getting fancy. 😉 But I like it. 🙂 Edited May 3, 2023 by Ian Branch Share this post Link to post
Fr0sT.Brutal 900 Posted May 3, 2023 function SetDBSessionNames(const Components: array of TComponent; const sSessionName: string): boolean; ? Share this post Link to post
programmerdelphi2k 237 Posted May 3, 2023 (edited) nevermind... I forgot that BDE dont propagate the "session name" automatically! Edited May 3, 2023 by programmerdelphi2k Share this post Link to post
Remy Lebeau 1394 Posted May 3, 2023 (edited) 10 hours ago, Ian Branch said: // if (Components[i] is TEDBSession) then (Components[i] as TEDBSession).SessionName := sSessionName; // if (Components[i] is TEDBDatabase) then (Components[i] as TEDBDatabase).SessionName := sSessionName; // if (Components[i] is TnlhTable) then (Components[i] as TnlhTable).SessionName := sSessionName; // if (Components[i] is TnlhQuery) then (Components[i] as TnlhQuery).SessionName := sSessionName; // if (Components[i] is TnlhScript) then (Components[i] as TnlhScript).SessionName := sSessionName; // Wow, that is just screaming for the SessionName to be moved into a common base class, or into a common interface that all of the components implement. If the TEDB... and Tnlh... components are from different libraries, I would simply derive my own classes from them, and define my own interface, eg: type IHaveASessionName = interface ['{6ea2f6fe-6b6f-4ea6-a893-12717e562329}'] function GetTheSessionName: string; procedure SetTheSessionName(const Value: string); property TheSessionName read GetTheSessionName write SetTheSessionName; end; ... type TMyEDBSession = class(TEDBSession, IHaveASessionName) function GetTheSessionName; procedure SetTheSessionName(const Value: string); end; function TMyEDBSession.GetTheSessionName; begin Result := SessionName; end; procedure TMyEDBSession.SetTheSessionName(const Value: string); begin SessionName := Value; end; // And repeat for TEDBDatabase, TnlhTable, TnlhQuery, TnlhScript, etc... ... for var i := 0 to ComponentCount - 1 do begin var Intf: IHaveASessionName; if Supports(Components[i], IHaveASessionName, Intf) then Intf.TheSessionName := sSessionName; end; If the components are on DFMs at design-time, you can alternatively use interposer classes in the DFM units, eg: type TEDBSession = class(edbcomps.TEDBSession, IHaveASessionName) function GetTheSessionName; procedure SetTheSessionName(const Value: string); end; // etc... Edited May 3, 2023 by Remy Lebeau Share this post Link to post