Skip to content

Instantly share code, notes, and snippets.

@jkour
Last active November 29, 2016 21:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkour/b45d3b35d9618cc4fac78452d2d3c272 to your computer and use it in GitHub Desktop.
Save jkour/b45d3b35d9618cc4fac78452d2d3c272 to your computer and use it in GitHub Desktop.
Global Classes with Generics
program Project3;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils, System.SyncObjs;
type
TGlobals<T: IInterface> = class
private
class var fInstance: T;
public
class function Instance: T;
class procedure createInstance (var aCreateFunc: TFunc<T>);
end;
//////////////////
IConfig = interface
['{BBE3E112-0158-4C1F-AF22-071E2C9423F7}']
procedure setConfigName (const aName: string);
function getConfigName: string;
property configName: string read getConfigName write setConfigName;
end;
TConfig = class (TInterfacedObject, IConfig)
private
fConfigName: string;
public
procedure setConfigName (const aName: string);
function getConfigName: string;
end;
IDatabase = interface
['{E39A54E7-4B07-4EBD-B9C0-C9808B92FEDB}']
procedure setDatabaseName (const aName: string);
function getDatabaseName: string;
property databaseName: string read getDatabaseName write setDatabaseName;
end;
TDatabase = class (TInterfacedObject, IDatabase)
private
fDatabaseName: string;
fConfig: IConfig;
public
constructor Create (const config: IConfig);
procedure setDatabaseName (const aName: string);
function getDatabaseName: string;
end;
{ TGlobals<T> }
{$REGION 'TGlobals<T>'}
class procedure TGlobals<T>.createInstance(var aCreateFunc: TFunc<T>);
begin
fInstance:=aCreateFunc;
end;
class function TGlobals<T>.Instance: T;
var
Lock: TCriticalSection;
begin
Lock:=TCriticalSection.Create;
try
Lock.Acquire;
if not Assigned(fInstance) then
raise Exception.Create('Call createTest first to instantiate');
Result:=fInstance;
Lock.Release;
finally
Lock.Free;
end;
end;
{$ENDREGION}
{ TConfig }
function TConfig.getConfigName: string;
begin
Result:=fConfigName;
end;
procedure TConfig.setConfigName(const aName: string);
begin
fConfigName:=aName;
end;
{ TDatabase }
constructor TDatabase.Create(const config: IConfig);
begin
fConfig:=config;
end;
function TDatabase.getDatabaseName: string;
begin
Result:=fDatabaseName;
end;
procedure TDatabase.setDatabaseName(const aName: string);
begin
fDatabaseName:=aName;
end;
var
tmpConfigFunc: TFunc<IConfig>;
tmpDatabaseFunc: TFunc<IDatabase>;
begin
ReportMemoryLeaksOnShutdown:=True;
try
tmpConfigFunc:= function: IConfig
begin
result:=TConfig.Create;
end;
TGlobals<IConfig>.createInstance(tmpConfigFunc);
TGlobals<IConfig>.Instance.configName:='My Config';
Writeln('Config Name: '+TGlobals<IConfig>.Instance.configName);
Readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment