Last active
November 29, 2016 21:21
-
-
Save jkour/b45d3b35d9618cc4fac78452d2d3c272 to your computer and use it in GitHub Desktop.
Global Classes with Generics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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