I am looking for a good solution for a decentralized module registration.
I do not want a single unit that uses all module units of the project, but I would rather like to let the module units register themselves.
The only solution I can think of is relying on initialization
of Delphi units.
I have written a test project:
Unit2
TForm2 = class(TForm)
private
class var FModules: TDictionary<string, TFormClass>;
public
class property Modules: TDictionary<string, TFormClass> read FModules;
procedure Run(const AName: string);
end;
procedure TForm2.Run(const AName: string);
begin
FModules[AName].Create(Self).ShowModal;
end;
initialization
TForm2.FModules := TDictionary<string, TFormClass>.Create;
finalization
TForm2.FModules.Free;
Unit3
TForm3 = class(TForm)
implementation
uses
Unit2;
initialization
TForm2.Modules.Add('Form3', TForm3);
Unit4
TForm4 = class(TForm)
implementation
uses
Unit2;
initialization
TForm2.Modules.Add('Form4', TForm4);
This has one drawback though. Is it guaranteed that my registration units (in this case Unit2
s) initialization
section is always run first?
I have often read warnings about initialization
sections, I know that I have to avoid raising exceptions in them.
Is it a good idea to use initialization sections for module registration?
Yes. Delphi's own framework uses it too, e.g. the registration of TGraphic
-descendents.
Is it guaranteed that my registration units (in this case Unit2s) initialization section is always run first?
Yes, according to the docs:
For units in the interface uses list, the initialization sections of the units used by a client are executed in the order in which the units appear in the client's uses clause.
But beware of the situation wherein you work with runtime packages.