delphimoduledelphi-xe3delphi-unitsinitialization-order

Is it a good idea to use initialization sections for module registration?


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 Unit2s) 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.


Solution

  • 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.