@@ -36,6 +36,9 @@ interface
36
36
uses
37
37
System.SysUtils,
38
38
RTTI,
39
+ { $IFDEF DEBUG_IOC}
40
+ Quick.Debug.Utils,
41
+ { $ENDIF}
39
42
System.TypInfo,
40
43
System.Generics.Collections,
41
44
Quick.Logger.Intf,
@@ -102,10 +105,12 @@ TIocRegistration<T> = record
102
105
TIocRegistrator = class (TInterfacedObject,IIocRegistrator)
103
106
private
104
107
fDependencies : TDictionary<string,TIocRegistration>;
108
+ fDependencyOrder : TList<TIocRegistration>;
105
109
public
106
110
constructor Create;
107
111
destructor Destroy; override;
108
112
property Dependencies : TDictionary<string,TIocRegistration> read fDependencies write fDependencies;
113
+ property DependencyOrder : TList<TIocRegistration> read fDependencyOrder;
109
114
function IsRegistered <TInterface: IInterface; TImplementation: class >(const aName : string = ' ' ) : Boolean; overload;
110
115
function IsRegistered <T>(const aName : string = ' ' ) : Boolean; overload;
111
116
function GetKey (aPInfo : PTypeInfo; const aName : string = ' ' ): string;
@@ -306,10 +311,19 @@ procedure TIocContainer.Build;
306
311
var
307
312
dependency : TIocRegistration;
308
313
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
310
318
begin
311
319
try
320
+ { $IFDEF DEBUG_IOC}
321
+ TDebugger.Trace(Self,' [Building container]: %s' ,[dependency.fIntfInfo.Name ]);
322
+ { $ENDIF}
312
323
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}
313
327
except
314
328
on E : Exception do raise EIocBuildError.CreateFmt(' Build Error on "%s(%s)" dependency: %s!' ,[dependency.fImplementation.ClassName,dependency.Name ,e.Message]);
315
329
end ;
@@ -415,25 +429,25 @@ function TIocContainer.ResolveAll<T>(const aName : string = ''): TList<T>;
415
429
constructor TIocRegistrator.Create;
416
430
begin
417
431
fDependencies := TDictionary<string,TIocRegistration>.Create;
432
+ fDependencyOrder := TList<TIocRegistration>.Create;
418
433
end ;
419
434
420
435
destructor TIocRegistrator.Destroy;
421
436
var
422
437
i : Integer;
423
438
regs : TArray<TIocRegistration>;
424
439
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
428
441
begin
429
- if regs [i]<> nil then
442
+ if fDependencyOrder [i] <> nil then
430
443
begin
431
444
// 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;
434
447
end ;
435
448
end ;
436
449
fDependencies.Free;
450
+ fDependencyOrder.Free;
437
451
inherited ;
438
452
end ;
439
453
@@ -504,6 +518,7 @@ function TIocRegistrator.RegisterInstance<TInterface>(aInstance: TInterface; con
504
518
TIocRegistrationInterface(Result).Instance := aInstance;
505
519
// reg.Instance := T.Create;
506
520
fDependencies.Add(key,Result);
521
+ fDependencyOrder.Add(Result);
507
522
end ;
508
523
end ;
509
524
@@ -523,6 +538,7 @@ function TIocRegistrator.RegisterInstance(aTypeInfo : PTypeInfo; const aName : s
523
538
Result.&Implementation := aTypeInfo.TypeData.ClassType;
524
539
// reg.Instance := T.Create;
525
540
fDependencies.Add(key,Result);
541
+ fDependencyOrder.Add(Result);
526
542
end ;
527
543
end ;
528
544
@@ -545,6 +561,7 @@ function TIocRegistrator.RegisterOptions<T>(aOptions: T): TIocRegistration<T>;
545
561
reg.&Implementation := aOptions.ClassType;
546
562
TIocRegistrationInterface(reg).Instance := TOptionValue<T>.Create(aOptions);
547
563
fDependencies.Add(key,reg);
564
+ fDependencyOrder.Add(reg);
548
565
end ;
549
566
Result := TIocRegistration<T>.Create(reg);
550
567
end ;
@@ -571,6 +588,7 @@ function TIocRegistrator.RegisterType(aTypeInfo : PTypeInfo; aImplementation : T
571
588
Result.IntfInfo := aTypeInfo;
572
589
Result.&Implementation := aImplementation;
573
590
fDependencies.Add(key,Result);
591
+ fDependencyOrder.Add(Result);
574
592
end ;
575
593
576
594
{ TIocResolver }
@@ -626,6 +644,9 @@ function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''
626
644
Result := nil ;
627
645
reg := nil ;
628
646
key := fRegistrator.GetKey(aServiceType,aName);
647
+ { $IFDEF DEBUG_IOC}
648
+ TDebugger.Trace(Self,' Resolving dependency: %s' ,[key]);
649
+ { $ENDIF}
629
650
if not fRegistrator.Dependencies.TryGetValue(key,reg) then raise EIocResolverError.CreateFmt(' Type "%s" not registered for IOC!' ,[aServiceType.Name ]);
630
651
// if is singleton return already instance if exists
631
652
if reg.IsSingleton then
@@ -636,6 +657,9 @@ function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''
636
657
begin
637
658
if TIocRegistrationInterface(reg).Instance.QueryInterface(GetTypeData(aServiceType).Guid,intf) <> 0 then raise EIocResolverError.CreateFmt(' Implementation for "%s" not registered!' ,[aServiceType.Name ]);
638
659
TValue.Make(@intf,aServiceType,Result);
660
+ { $IFDEF DEBUG_IOC}
661
+ TDebugger.Trace(Self,' Resolved dependency: %s' ,[reg.fIntfInfo.Name ]);
662
+ { $ENDIF}
639
663
Exit;
640
664
end ;
641
665
end
@@ -644,6 +668,9 @@ function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''
644
668
if TIocRegistrationInstance(reg).Instance <> nil then
645
669
begin
646
670
Result := TIocRegistrationInstance(reg).Instance;
671
+ { $IFDEF DEBUG_IOC}
672
+ TDebugger.Trace(Self,' Resolved dependency: %s' ,[reg.fIntfInfo.Name ]);
673
+ { $ENDIF}
647
674
Exit;
648
675
end ;
649
676
end ;
@@ -653,20 +680,29 @@ function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''
653
680
// use activator if assigned
654
681
if reg is TIocRegistrationInterface then
655
682
begin
683
+ { $IFDEF DEBUG_IOC}
684
+ TDebugger.Trace(Self,' Building dependency: %s' ,[reg.fIntfInfo.Name ]);
685
+ { $ENDIF}
656
686
if Assigned(reg.ActivatorDelegate) then TIocRegistrationInterface(reg).Instance := reg.ActivatorDelegate().AsInterface
657
687
else TIocRegistrationInterface(reg).Instance := CreateInstance(reg.&Implementation ).AsInterface;
658
688
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 ]);
659
689
TValue.Make(@intf,aServiceType,Result);
660
690
end
661
691
else
662
692
begin
693
+ { $IFDEF DEBUG_IOC}
694
+ TDebugger.Trace(Self,' Building dependency: %s' ,[reg.fIntfInfo.Name ]);
695
+ { $ENDIF}
663
696
if Assigned(reg.ActivatorDelegate) then TIocRegistrationInstance(reg).Instance := reg.ActivatorDelegate().AsObject
664
697
else
665
698
begin
666
699
TIocRegistrationInstance(reg).Instance := CreateInstance(reg.&Implementation ).AsObject;
667
700
end ;
668
701
Result := TIocRegistrationInstance(reg).Instance;
669
702
end ;
703
+ { $IFDEF DEBUG_IOC}
704
+ TDebugger.Trace(Self,' Built dependency: %s' ,[reg.fIntfInfo.Name ]);
705
+ { $ENDIF}
670
706
end ;
671
707
672
708
function TIocResolver.Resolve <T>(const aName : string = ' ' ): T;
@@ -687,7 +723,7 @@ function TIocResolver.ResolveAll<T>(const aName : string = '') : TList<T>;
687
723
Result := TList<T>.Create;
688
724
pInfo := TypeInfo(T);
689
725
690
- for reg in fRegistrator.Dependencies.Values do
726
+ for reg in fRegistrator.fDependencyOrder do
691
727
begin
692
728
if reg.IntfInfo = pInfo then Self.Resolve(pInfo,aName);
693
729
end ;
0 commit comments