소스 검색

[ioc] ResolveAll<T> method

Exilon 5 년 전
부모
커밋
b440a17093
1개의 변경된 파일59개의 추가작업 그리고 45개의 파일을 삭제
  1. 59 45
      Quick.IOC.pas

+ 59 - 45
Quick.IOC.pas

@@ -7,7 +7,7 @@
   Author      : Kike Pérez
   Version     : 1.0
   Created     : 19/10/2019
-  Modified    : 10/03/2020
+  Modified    : 12/03/2020
 
   This file is part of QuickLib: https://github.com/exilon/QuickLib
 
@@ -144,6 +144,7 @@ type
     constructor Create(aRegistrator : TIocRegistrator; aInjector : TIocInjector);
     function Resolve<T>(const aName : string = ''): T; overload;
     function Resolve(aServiceType: PTypeInfo; const aName : string = ''): TValue; overload;
+    function ResolveAll<T>(const aName : string = '') : TList<T>;
   end;
 
   TIocContainer = class(TInterfacedObject,IIocContainer)
@@ -172,6 +173,7 @@ type
     function RegisterOptions<T : TOptions>(aOptions : TConfigureOptionsProc<T>) : TIocRegistration<T>; overload;
     function Resolve<T>(const aName : string = ''): T; overload;
     function Resolve(aServiceType: PTypeInfo; const aName : string = ''): TValue; overload;
+    function ResolveAll<T>(const aName : string = '') : TList<T>;
     function AbstractFactory<T : class, constructor>(aClass : TClass) : T; overload;
     function AbstractFactory<T : class, constructor> : T; overload;
   end;
@@ -275,18 +277,13 @@ var
   rtype : TRttiType;
   rtypei : TRttiInterfaceType;
 begin
-  ctx := TRttiContext.Create;
-  try
-    for rtype in ctx.GetTypes do
-      begin
-        if rtype.TypeKind = TTypeKind.tkInterface then
-        begin
-          rtypei := (rtype as TRttiInterfaceType);
-          if IsEqualGUID(rtypei.GUID,AGUID) then Exit(rtypei.Handle);
-        end;
-      end;
-  finally
-    ctx.Free;
+  for rtype in ctx.GetTypes do
+  begin
+    if rtype.TypeKind = TTypeKind.tkInterface then
+    begin
+      rtypei := (rtype as TRttiInterfaceType);
+      if IsEqualGUID(rtypei.GUID,AGUID) then Exit(rtypei.Handle);
+    end;
   end;
   Result := nil;
 end;
@@ -350,6 +347,11 @@ begin
   Result := fResolver.Resolve<T>(aName);
 end;
 
+function TIocContainer.ResolveAll<T>(const aName : string = ''): TList<T>;
+begin
+  Result := fResolver.ResolveAll<T>(aName);
+end;
+
 { TIocRegistrator }
 
 constructor TIocRegistrator.Create;
@@ -406,7 +408,8 @@ begin
   key := GetKey(TypeInfo(TInterface),aName);
   if fDependencies.TryGetValue(key,reg) then
   begin
-    if (reg is TIocRegistrationInterface) and (TIocRegistrationInterface(reg).Instance <> nil) then Result := True;
+    //if (reg is TIocRegistrationInterface) and (TIocRegistrationInterface(reg).Instance <> nil) then Result := True;
+    if reg is TIocRegistrationInterface then Result := True;
   end
 end;
 
@@ -496,15 +499,13 @@ begin
   key := GetKey(aTypeInfo,aName);
   if fDependencies.TryGetValue(key,Result) then
   begin
-    if Result.&Implementation = aImplementation then raise EIocRegisterError.Create('Implementation for this interface is already registered!');
-  end
-  else
-  begin
-    Result := TIocRegistrationInterface.Create;
-    Result.IntfInfo := aTypeInfo;
-    Result.&Implementation := aImplementation;
-    fDependencies.Add(key,Result);
+    if Result.&Implementation = aImplementation then raise EIocRegisterError.Create('Implementation for this interface is already registered!')
+      else Key := key + '#' + TGUID.NewGuid.ToString;
   end;
+  Result := TIocRegistrationInterface.Create;
+  Result.IntfInfo := aTypeInfo;
+  Result.&Implementation := aImplementation;
+  fDependencies.Add(key,Result);
 end;
 
 { TIocResolver }
@@ -525,34 +526,29 @@ var
   values : TArray<TValue>;
 begin
   Result := nil;
-  ctx := TRttiContext.Create;
-  try
-    rtype := ctx.GetType(aClass);
-    if rtype = nil then Exit;
-    for rmethod in TRttiInstanceType(rtype).GetMethods do
+  rtype := ctx.GetType(aClass);
+  if rtype = nil then Exit;
+  for rmethod in TRttiInstanceType(rtype).GetMethods do
+  begin
+    if rmethod.IsConstructor then
     begin
-      if rmethod.IsConstructor then
+      //if create don't have parameters
+      if Length(rmethod.GetParameters) = 0 then
       begin
-        //if create don't have parameters
-        if Length(rmethod.GetParameters) = 0 then
-        begin
-          Result := rmethod.Invoke(TRttiInstanceType(rtype).MetaclassType,[]);
-          Break;
-        end
-        else
+        Result := rmethod.Invoke(TRttiInstanceType(rtype).MetaclassType,[]);
+        Break;
+      end
+      else
+      begin
+        for rParam in rmethod.GetParameters do
         begin
-          for rParam in rmethod.GetParameters do
-          begin
-            value := Resolve(rParam.ParamType.Handle);
-            values := values + [value];
-          end;
-          Result := rmethod.Invoke(TRttiInstanceType(rtype).MetaclassType,values);
-          Break;
+          value := Resolve(rParam.ParamType.Handle);
+          values := values + [value];
         end;
+        Result := rmethod.Invoke(TRttiInstanceType(rtype).MetaclassType,values);
+        Break;
       end;
     end;
-  finally
-    ctx.Free;
   end;
 end;
 
@@ -565,7 +561,7 @@ begin
   Result := nil;
   reg := nil;
   key := fRegistrator.GetKey(aServiceType,aName);
-  if not fRegistrator.Dependencies.TryGetValue(key,reg) then raise EIocResolverError.CreateFmt('Type "%s" not register for IOC!',[aServiceType.Name]);
+  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
   begin
@@ -618,6 +614,24 @@ begin
   Result := Resolve(pInfo,aName).AsType<T>;
 end;
 
+function TIocResolver.ResolveAll<T>(const aName : string = '') : TList<T>;
+var
+  pInfo : PTypeInfo;
+  reg : TIocRegistration;
+  pair : TPair<string,TIocRegistration>;
+begin
+  Result := TList<T>.Create;
+  pInfo := TypeInfo(T);
+
+  for pair in fRegistrator.Dependencies.ToArray do
+  begin
+    reg := pair.Value;
+    //var a := pair.Key;
+    if reg.IntfInfo = pInfo then Self.Resolve(pInfo,aName);
+  end;
+
+end;
+
 { TIocRegistration<T> }
 
 function TIocRegistration<T>.AsScoped: TIocRegistration<T>;