Browse Source

[ioc] some improvements

Exilon 3 years ago
parent
commit
bc20c359d3
1 changed files with 44 additions and 8 deletions
  1. 44 8
      Quick.IOC.pas

+ 44 - 8
Quick.IOC.pas

@@ -36,6 +36,9 @@ interface
 uses
   System.SysUtils,
   RTTI,
+  {$IFDEF DEBUG_IOC}
+    Quick.Debug.Utils,
+  {$ENDIF}
   System.TypInfo,
   System.Generics.Collections,
   Quick.Logger.Intf,
@@ -102,10 +105,12 @@ type
   TIocRegistrator = class(TInterfacedObject,IIocRegistrator)
   private
     fDependencies : TDictionary<string,TIocRegistration>;
+    fDependencyOrder : TList<TIocRegistration>;
   public
     constructor Create;
     destructor Destroy; override;
     property Dependencies : TDictionary<string,TIocRegistration> read fDependencies write fDependencies;
+    property DependencyOrder : TList<TIocRegistration> read fDependencyOrder;
     function IsRegistered<TInterface: IInterface; TImplementation: class>(const aName : string = '') : Boolean; overload;
     function IsRegistered<T>(const aName : string = '') : Boolean; overload;
     function GetKey(aPInfo : PTypeInfo; const aName : string = ''): string;
@@ -306,10 +311,19 @@ procedure TIocContainer.Build;
 var
   dependency : TIocRegistration;
 begin
-  for dependency in fRegistrator.Dependencies.Values do
+  {$IFDEF DEBUG_IOC}
+  TDebugger.TimeIt(Self,'Build','Container dependencies building...');
+  {$ENDIF}
+  for dependency in fRegistrator.DependencyOrder do
   begin
     try
+      {$IFDEF DEBUG_IOC}
+      TDebugger.Trace(Self,'[Building container]: %s',[dependency.fIntfInfo.Name]);
+      {$ENDIF}
       if dependency.IsSingleton then fResolver.Resolve(dependency.fIntfInfo,dependency.Name);
+      {$IFDEF DEBUG_IOC}
+      TDebugger.Trace(Self,'[Built container]: %s',[dependency.fIntfInfo.Name]);
+      {$ENDIF}
     except
       on E : Exception do raise EIocBuildError.CreateFmt('Build Error on "%s(%s)" dependency: %s!',[dependency.fImplementation.ClassName,dependency.Name,e.Message]);
     end;
@@ -415,6 +429,7 @@ end;
 constructor TIocRegistrator.Create;
 begin
   fDependencies := TDictionary<string,TIocRegistration>.Create;
+  fDependencyOrder := TList<TIocRegistration>.Create;
 end;
 
 destructor TIocRegistrator.Destroy;
@@ -422,18 +437,17 @@ var
   i : Integer;
   regs : TArray<TIocRegistration>;
 begin
-  //for reg in fDependencies.Values do
-  regs := fDependencies.Values.ToArray;
-  for i := High(regs) downto Low(regs) do
+  for i := fDependencyOrder.Count-1 downto 0 do
   begin
-    if regs[i]<> nil then
+    if fDependencyOrder[i] <> nil then
     begin
       //free singleton instances not interfaced
-      if (regs[i] is TIocRegistrationInstance) and (TIocRegistrationInstance(regs[i]).IsSingleton) then TIocRegistrationInstance(regs[i]).Instance.Free;
-      regs[i].Free;
+      if (fDependencyOrder[i] is TIocRegistrationInstance) and (TIocRegistrationInstance(fDependencyOrder[i]).IsSingleton) then TIocRegistrationInstance(regs[i]).Instance.Free;
+      fDependencyOrder[i].Free;
     end;
   end;
   fDependencies.Free;
+  fDependencyOrder.Free;
   inherited;
 end;
 
@@ -504,6 +518,7 @@ begin
     TIocRegistrationInterface(Result).Instance := aInstance;
     //reg.Instance := T.Create;
     fDependencies.Add(key,Result);
+    fDependencyOrder.Add(Result);
   end;
 end;
 
@@ -523,6 +538,7 @@ begin
     Result.&Implementation := aTypeInfo.TypeData.ClassType;
     //reg.Instance := T.Create;
     fDependencies.Add(key,Result);
+    fDependencyOrder.Add(Result);
   end;
 end;
 
@@ -545,6 +561,7 @@ begin
     reg.&Implementation := aOptions.ClassType;
     TIocRegistrationInterface(reg).Instance := TOptionValue<T>.Create(aOptions);
     fDependencies.Add(key,reg);
+    fDependencyOrder.Add(reg);
   end;
   Result := TIocRegistration<T>.Create(reg);
 end;
@@ -571,6 +588,7 @@ begin
   Result.IntfInfo := aTypeInfo;
   Result.&Implementation := aImplementation;
   fDependencies.Add(key,Result);
+  fDependencyOrder.Add(Result);
 end;
 
 { TIocResolver }
@@ -626,6 +644,9 @@ begin
   Result := nil;
   reg := nil;
   key := fRegistrator.GetKey(aServiceType,aName);
+  {$IFDEF DEBUG_IOC}
+  TDebugger.Trace(Self,'Resolving dependency: %s',[key]);
+  {$ENDIF}
   if not fRegistrator.Dependencies.TryGetValue(key,reg) then raise EIocResolverError.CreateFmt('Type "%s" not registered for IOC!',[aServiceType.Name]);
   //if is singleton return already instance if exists
   if reg.IsSingleton then
@@ -636,6 +657,9 @@ begin
       begin
         if TIocRegistrationInterface(reg).Instance.QueryInterface(GetTypeData(aServiceType).Guid,intf) <> 0 then raise EIocResolverError.CreateFmt('Implementation for "%s" not registered!',[aServiceType.Name]);
         TValue.Make(@intf,aServiceType,Result);
+        {$IFDEF DEBUG_IOC}
+        TDebugger.Trace(Self,'Resolved dependency: %s',[reg.fIntfInfo.Name]);
+        {$ENDIF}
         Exit;
       end;
     end
@@ -644,6 +668,9 @@ begin
       if TIocRegistrationInstance(reg).Instance <> nil then
       begin
         Result := TIocRegistrationInstance(reg).Instance;
+        {$IFDEF DEBUG_IOC}
+        TDebugger.Trace(Self,'Resolved dependency: %s',[reg.fIntfInfo.Name]);
+        {$ENDIF}
         Exit;
       end;
     end;
@@ -653,6 +680,9 @@ begin
   //use activator if assigned
   if reg is TIocRegistrationInterface then
   begin
+    {$IFDEF DEBUG_IOC}
+    TDebugger.Trace(Self,'Building dependency: %s',[reg.fIntfInfo.Name]);
+    {$ENDIF}
     if Assigned(reg.ActivatorDelegate) then TIocRegistrationInterface(reg).Instance := reg.ActivatorDelegate().AsInterface
       else TIocRegistrationInterface(reg).Instance := CreateInstance(reg.&Implementation).AsInterface;
     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]);
@@ -660,6 +690,9 @@ begin
   end
   else
   begin
+    {$IFDEF DEBUG_IOC}
+    TDebugger.Trace(Self,'Building dependency: %s',[reg.fIntfInfo.Name]);
+    {$ENDIF}
     if Assigned(reg.ActivatorDelegate) then TIocRegistrationInstance(reg).Instance := reg.ActivatorDelegate().AsObject
     else
     begin
@@ -667,6 +700,9 @@ begin
     end;
     Result := TIocRegistrationInstance(reg).Instance;
   end;
+  {$IFDEF DEBUG_IOC}
+  TDebugger.Trace(Self,'Built dependency: %s',[reg.fIntfInfo.Name]);
+  {$ENDIF}
 end;
 
 function TIocResolver.Resolve<T>(const aName : string = ''): T;
@@ -687,7 +723,7 @@ begin
   Result := TList<T>.Create;
   pInfo := TypeInfo(T);
 
-  for reg in fRegistrator.Dependencies.Values do
+  for reg in fRegistrator.fDependencyOrder do
   begin
     if reg.IntfInfo = pInfo then Self.Resolve(pInfo,aName);
   end;