Skip to content

Commit bc20c35

Browse files
committed
[ioc] some improvements
1 parent 99aa60e commit bc20c35

File tree

1 file changed

+44
-8
lines changed

1 file changed

+44
-8
lines changed

Quick.IOC.pas

+44-8
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ interface
3636
uses
3737
System.SysUtils,
3838
RTTI,
39+
{$IFDEF DEBUG_IOC}
40+
Quick.Debug.Utils,
41+
{$ENDIF}
3942
System.TypInfo,
4043
System.Generics.Collections,
4144
Quick.Logger.Intf,
@@ -102,10 +105,12 @@ TIocRegistration<T> = record
102105
TIocRegistrator = class(TInterfacedObject,IIocRegistrator)
103106
private
104107
fDependencies : TDictionary<string,TIocRegistration>;
108+
fDependencyOrder : TList<TIocRegistration>;
105109
public
106110
constructor Create;
107111
destructor Destroy; override;
108112
property Dependencies : TDictionary<string,TIocRegistration> read fDependencies write fDependencies;
113+
property DependencyOrder : TList<TIocRegistration> read fDependencyOrder;
109114
function IsRegistered<TInterface: IInterface; TImplementation: class>(const aName : string = '') : Boolean; overload;
110115
function IsRegistered<T>(const aName : string = '') : Boolean; overload;
111116
function GetKey(aPInfo : PTypeInfo; const aName : string = ''): string;
@@ -306,10 +311,19 @@ procedure TIocContainer.Build;
306311
var
307312
dependency : TIocRegistration;
308313
begin
309-
for dependency in fRegistrator.Dependencies.Values do
314+
{$IFDEF DEBUG_IOC}
315+
TDebugger.TimeIt(Self,'Build','Container dependencies building...');
316+
{$ENDIF}
317+
for dependency in fRegistrator.DependencyOrder do
310318
begin
311319
try
320+
{$IFDEF DEBUG_IOC}
321+
TDebugger.Trace(Self,'[Building container]: %s',[dependency.fIntfInfo.Name]);
322+
{$ENDIF}
312323
if dependency.IsSingleton then fResolver.Resolve(dependency.fIntfInfo,dependency.Name);
324+
{$IFDEF DEBUG_IOC}
325+
TDebugger.Trace(Self,'[Built container]: %s',[dependency.fIntfInfo.Name]);
326+
{$ENDIF}
313327
except
314328
on E : Exception do raise EIocBuildError.CreateFmt('Build Error on "%s(%s)" dependency: %s!',[dependency.fImplementation.ClassName,dependency.Name,e.Message]);
315329
end;
@@ -415,25 +429,25 @@ function TIocContainer.ResolveAll<T>(const aName : string = ''): TList<T>;
415429
constructor TIocRegistrator.Create;
416430
begin
417431
fDependencies := TDictionary<string,TIocRegistration>.Create;
432+
fDependencyOrder := TList<TIocRegistration>.Create;
418433
end;
419434

420435
destructor TIocRegistrator.Destroy;
421436
var
422437
i : Integer;
423438
regs : TArray<TIocRegistration>;
424439
begin
425-
//for reg in fDependencies.Values do
426-
regs := fDependencies.Values.ToArray;
427-
for i := High(regs) downto Low(regs) do
440+
for i := fDependencyOrder.Count-1 downto 0 do
428441
begin
429-
if regs[i]<> nil then
442+
if fDependencyOrder[i] <> nil then
430443
begin
431444
//free singleton instances not interfaced
432-
if (regs[i] is TIocRegistrationInstance) and (TIocRegistrationInstance(regs[i]).IsSingleton) then TIocRegistrationInstance(regs[i]).Instance.Free;
433-
regs[i].Free;
445+
if (fDependencyOrder[i] is TIocRegistrationInstance) and (TIocRegistrationInstance(fDependencyOrder[i]).IsSingleton) then TIocRegistrationInstance(regs[i]).Instance.Free;
446+
fDependencyOrder[i].Free;
434447
end;
435448
end;
436449
fDependencies.Free;
450+
fDependencyOrder.Free;
437451
inherited;
438452
end;
439453

@@ -504,6 +518,7 @@ function TIocRegistrator.RegisterInstance<TInterface>(aInstance: TInterface; con
504518
TIocRegistrationInterface(Result).Instance := aInstance;
505519
//reg.Instance := T.Create;
506520
fDependencies.Add(key,Result);
521+
fDependencyOrder.Add(Result);
507522
end;
508523
end;
509524

@@ -523,6 +538,7 @@ function TIocRegistrator.RegisterInstance(aTypeInfo : PTypeInfo; const aName : s
523538
Result.&Implementation := aTypeInfo.TypeData.ClassType;
524539
//reg.Instance := T.Create;
525540
fDependencies.Add(key,Result);
541+
fDependencyOrder.Add(Result);
526542
end;
527543
end;
528544

@@ -545,6 +561,7 @@ function TIocRegistrator.RegisterOptions<T>(aOptions: T): TIocRegistration<T>;
545561
reg.&Implementation := aOptions.ClassType;
546562
TIocRegistrationInterface(reg).Instance := TOptionValue<T>.Create(aOptions);
547563
fDependencies.Add(key,reg);
564+
fDependencyOrder.Add(reg);
548565
end;
549566
Result := TIocRegistration<T>.Create(reg);
550567
end;
@@ -571,6 +588,7 @@ function TIocRegistrator.RegisterType(aTypeInfo : PTypeInfo; aImplementation : T
571588
Result.IntfInfo := aTypeInfo;
572589
Result.&Implementation := aImplementation;
573590
fDependencies.Add(key,Result);
591+
fDependencyOrder.Add(Result);
574592
end;
575593

576594
{ TIocResolver }
@@ -626,6 +644,9 @@ function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''
626644
Result := nil;
627645
reg := nil;
628646
key := fRegistrator.GetKey(aServiceType,aName);
647+
{$IFDEF DEBUG_IOC}
648+
TDebugger.Trace(Self,'Resolving dependency: %s',[key]);
649+
{$ENDIF}
629650
if not fRegistrator.Dependencies.TryGetValue(key,reg) then raise EIocResolverError.CreateFmt('Type "%s" not registered for IOC!',[aServiceType.Name]);
630651
//if is singleton return already instance if exists
631652
if reg.IsSingleton then
@@ -636,6 +657,9 @@ function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''
636657
begin
637658
if TIocRegistrationInterface(reg).Instance.QueryInterface(GetTypeData(aServiceType).Guid,intf) <> 0 then raise EIocResolverError.CreateFmt('Implementation for "%s" not registered!',[aServiceType.Name]);
638659
TValue.Make(@intf,aServiceType,Result);
660+
{$IFDEF DEBUG_IOC}
661+
TDebugger.Trace(Self,'Resolved dependency: %s',[reg.fIntfInfo.Name]);
662+
{$ENDIF}
639663
Exit;
640664
end;
641665
end
@@ -644,6 +668,9 @@ function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''
644668
if TIocRegistrationInstance(reg).Instance <> nil then
645669
begin
646670
Result := TIocRegistrationInstance(reg).Instance;
671+
{$IFDEF DEBUG_IOC}
672+
TDebugger.Trace(Self,'Resolved dependency: %s',[reg.fIntfInfo.Name]);
673+
{$ENDIF}
647674
Exit;
648675
end;
649676
end;
@@ -653,20 +680,29 @@ function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''
653680
//use activator if assigned
654681
if reg is TIocRegistrationInterface then
655682
begin
683+
{$IFDEF DEBUG_IOC}
684+
TDebugger.Trace(Self,'Building dependency: %s',[reg.fIntfInfo.Name]);
685+
{$ENDIF}
656686
if Assigned(reg.ActivatorDelegate) then TIocRegistrationInterface(reg).Instance := reg.ActivatorDelegate().AsInterface
657687
else TIocRegistrationInterface(reg).Instance := CreateInstance(reg.&Implementation).AsInterface;
658688
if (TIocRegistrationInterface(reg).Instance = nil) or (TIocRegistrationInterface(reg).Instance.QueryInterface(GetTypeData(aServiceType).Guid,intf) <> 0) then raise EIocResolverError.CreateFmt('Implementation for "%s" not registered!',[aServiceType.Name]);
659689
TValue.Make(@intf,aServiceType,Result);
660690
end
661691
else
662692
begin
693+
{$IFDEF DEBUG_IOC}
694+
TDebugger.Trace(Self,'Building dependency: %s',[reg.fIntfInfo.Name]);
695+
{$ENDIF}
663696
if Assigned(reg.ActivatorDelegate) then TIocRegistrationInstance(reg).Instance := reg.ActivatorDelegate().AsObject
664697
else
665698
begin
666699
TIocRegistrationInstance(reg).Instance := CreateInstance(reg.&Implementation).AsObject;
667700
end;
668701
Result := TIocRegistrationInstance(reg).Instance;
669702
end;
703+
{$IFDEF DEBUG_IOC}
704+
TDebugger.Trace(Self,'Built dependency: %s',[reg.fIntfInfo.Name]);
705+
{$ENDIF}
670706
end;
671707

672708
function TIocResolver.Resolve<T>(const aName : string = ''): T;
@@ -687,7 +723,7 @@ function TIocResolver.ResolveAll<T>(const aName : string = '') : TList<T>;
687723
Result := TList<T>.Create;
688724
pInfo := TypeInfo(T);
689725

690-
for reg in fRegistrator.Dependencies.Values do
726+
for reg in fRegistrator.fDependencyOrder do
691727
begin
692728
if reg.IntfInfo = pInfo then Self.Resolve(pInfo,aName);
693729
end;

0 commit comments

Comments
 (0)