Quick.IOC.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. { ***************************************************************************
  2. Copyright (c) 2016-2020 Kike Pérez
  3. Unit : Quick.IoC
  4. Description : IoC Dependency Injector
  5. Author : Kike Pérez
  6. Version : 1.0
  7. Created : 19/10/2019
  8. Modified : 12/03/2020
  9. This file is part of QuickLib: https://github.com/exilon/QuickLib
  10. ***************************************************************************
  11. Licensed under the Apache License, Version 2.0 (the "License");
  12. you may not use this file except in compliance with the License.
  13. You may obtain a copy of the License at
  14. http://www.apache.org/licenses/LICENSE-2.0
  15. Unless required by applicable law or agreed to in writing, software
  16. distributed under the License is distributed on an "AS IS" BASIS,
  17. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. See the License for the specific language governing permissions and
  19. limitations under the License.
  20. *************************************************************************** }
  21. unit Quick.IoC;
  22. {$i QuickLib.inc}
  23. interface
  24. uses
  25. System.SysUtils,
  26. RTTI,
  27. System.TypInfo,
  28. System.Generics.Collections,
  29. Quick.Logger.Intf,
  30. Quick.Options;
  31. type
  32. TActivatorDelegate<T> = reference to function: T;
  33. TIocRegistration = class
  34. type
  35. TRegisterMode = (rmTransient, rmSingleton, rmScoped);
  36. private
  37. fRegisterMode : TRegisterMode;
  38. fIntfInfo : PTypeInfo;
  39. fImplementation : TClass;
  40. fActivatorDelegate : TActivatorDelegate<TValue>;
  41. public
  42. constructor Create;
  43. property IntfInfo : PTypeInfo read fIntfInfo write fIntfInfo;
  44. property &Implementation : TClass read fImplementation write fImplementation;
  45. function IsSingleton : Boolean;
  46. function IsTransient : Boolean;
  47. function IsScoped : Boolean;
  48. function AsSingleton : TIocRegistration;
  49. function AsTransient : TIocRegistration;
  50. function AsScoped : TIocRegistration;
  51. property ActivatorDelegate : TActivatorDelegate<TValue> read fActivatorDelegate write fActivatorDelegate;
  52. end;
  53. TIocRegistrationInterface = class(TIocRegistration)
  54. private
  55. fInstance : IInterface;
  56. public
  57. property Instance : IInterface read fInstance write fInstance;
  58. end;
  59. TIocRegistrationInstance = class(TIocRegistration)
  60. private
  61. fInstance : TObject;
  62. public
  63. property Instance : TObject read fInstance write fInstance;
  64. end;
  65. TIocRegistration<T> = record
  66. private
  67. fRegistration : TIocRegistration;
  68. public
  69. constructor Create(aRegistration : TIocRegistration);
  70. function AsSingleton : TIocRegistration<T>;
  71. function AsTransient : TIocRegistration<T>;
  72. function AsScoped : TIocRegistration<T>;
  73. function DelegateTo(aDelegate : TActivatorDelegate<T>) : TIocRegistration<T>;
  74. end;
  75. IIocRegistrator = interface
  76. ['{F3B79B15-2874-4B66-9B7F-06E2EBFED1AE}']
  77. function GetKey(aPInfo : PTypeInfo; const aName : string = ''): string;
  78. function RegisterType(aTypeInfo : PTypeInfo; aImplementation : TClass; const aName : string = '') : TIocRegistration;
  79. function RegisterInstance(aTypeInfo : PTypeInfo; const aName : string = '') : TIocRegistration;
  80. end;
  81. TIocRegistrator = class(TInterfacedObject,IIocRegistrator)
  82. private
  83. fDependencies : TDictionary<string,TIocRegistration>;
  84. public
  85. constructor Create;
  86. destructor Destroy; override;
  87. property Dependencies : TDictionary<string,TIocRegistration> read fDependencies write fDependencies;
  88. function IsRegistered<TInterface: IInterface; TImplementation: class>(const aName : string = '') : Boolean; overload;
  89. function IsRegistered<TInterface : IInterface>(const aName : string = '') : Boolean; overload;
  90. function GetKey(aPInfo : PTypeInfo; const aName : string = ''): string;
  91. function RegisterType<TInterface: IInterface; TImplementation: class>(const aName : string = '') : TIocRegistration<TImplementation>; overload;
  92. function RegisterType(aTypeInfo : PTypeInfo; aImplementation : TClass; const aName : string = '') : TIocRegistration; overload;
  93. function RegisterInstance(aTypeInfo : PTypeInfo; const aName : string = '') : TIocRegistration; overload;
  94. function RegisterInstance<T : class>(const aName : string = '') : TIocRegistration<T>; overload;
  95. function RegisterInstance<TInterface : IInterface>(aInstance : TInterface; const aName : string = '') : TIocRegistration; overload;
  96. function RegisterOptions<T : TOptions>(aOptions : T) : TIocRegistration<T>;
  97. end;
  98. IIocContainer = interface
  99. ['{6A486E3C-C5E8-4BE5-8382-7B9BCCFC1BC3}']
  100. function RegisterType(aInterface: PTypeInfo; aImplementation : TClass; const aName : string = '') : TIocRegistration;
  101. function RegisterInstance(aTypeInfo : PTypeInfo; const aName : string = '') : TIocRegistration;
  102. function Resolve(aServiceType: PTypeInfo; const aName : string = ''): TValue;
  103. //procedure Build;
  104. end;
  105. IIocInjector = interface
  106. ['{F78E6BBC-2A95-41C9-B231-D05A586B4B49}']
  107. end;
  108. TIocInjector = class(TInterfacedObject,IIocInjector)
  109. end;
  110. IIocResolver = interface
  111. ['{B7C07604-B862-46B2-BF33-FF941BBE53CA}']
  112. function Resolve(aServiceType: PTypeInfo; const aName : string = ''): TValue; overload;
  113. end;
  114. TIocResolver = class(TInterfacedObject,IIocResolver)
  115. private
  116. fRegistrator : TIocRegistrator;
  117. fInjector : TIocInjector;
  118. function CreateInstance(aClass : TClass) : TValue;
  119. public
  120. constructor Create(aRegistrator : TIocRegistrator; aInjector : TIocInjector);
  121. function Resolve<T>(const aName : string = ''): T; overload;
  122. function Resolve(aServiceType: PTypeInfo; const aName : string = ''): TValue; overload;
  123. function ResolveAll<T>(const aName : string = '') : TList<T>;
  124. end;
  125. TIocContainer = class(TInterfacedObject,IIocContainer)
  126. private
  127. fRegistrator : TIocRegistrator;
  128. fResolver : TIocResolver;
  129. fInjector : TIocInjector;
  130. fLogger : ILogger;
  131. function InterfaceTypeInfo(const AGUID : TGUID) : PTypeInfo;
  132. class var
  133. GlobalInstance: TIocContainer;
  134. protected
  135. class constructor Create;
  136. class destructor Destroy;
  137. public
  138. constructor Create;
  139. destructor Destroy; override;
  140. function IsRegistered<TInterface: IInterface; TImplementation: class>(const aName: string): Boolean; overload;
  141. function IsRegistered<TInterface : IInterface>(const aName: string): Boolean; overload;
  142. function RegisterType<TInterface: IInterface; TImplementation: class>(const aName : string = '') : TIocRegistration<TImplementation>; overload;
  143. function RegisterType(aInterface: PTypeInfo; aImplementation : TClass; const aName : string = '') : TIocRegistration; overload;
  144. function RegisterInstance<T : class>(const aName: string = ''): TIocRegistration<T>; overload;
  145. function RegisterInstance(aTypeInfo : PTypeInfo; const aName : string = '') : TIocRegistration; overload;
  146. function RegisterInstance<TInterface : IInterface>(aInstance : TInterface; const aName : string = '') : TIocRegistration; overload;
  147. function RegisterOptions<T : TOptions>(aOptions : TOptions) : TIocRegistration<T>; overload;
  148. function RegisterOptions<T : TOptions>(aOptions : TConfigureOptionsProc<T>) : TIocRegistration<T>; overload;
  149. function Resolve<T>(const aName : string = ''): T; overload;
  150. function Resolve(aServiceType: PTypeInfo; const aName : string = ''): TValue; overload;
  151. function ResolveAll<T>(const aName : string = '') : TList<T>;
  152. function AbstractFactory<T : class, constructor>(aClass : TClass) : T; overload;
  153. function AbstractFactory<T : class, constructor> : T; overload;
  154. end;
  155. EIocRegisterError = class(Exception);
  156. EIocResolverError = class(Exception);
  157. //singleton global instance
  158. function GlobalContainer: TIocContainer;
  159. implementation
  160. function GlobalContainer: TIocContainer;
  161. begin
  162. Result := TIocContainer.GlobalInstance;
  163. end;
  164. { TIocRegistration }
  165. constructor TIocRegistration.Create;
  166. begin
  167. fRegisterMode := TRegisterMode.rmTransient;
  168. end;
  169. function TIocRegistration.AsTransient: TIocRegistration;
  170. begin
  171. Result := Self;
  172. fRegisterMode := TRegisterMode.rmTransient;
  173. end;
  174. function TIocRegistration.AsSingleton : TIocRegistration;
  175. begin
  176. Result := Self;
  177. fRegisterMode := TRegisterMode.rmSingleton;
  178. end;
  179. function TIocRegistration.AsScoped: TIocRegistration;
  180. begin
  181. Result := Self;
  182. fRegisterMode := TRegisterMode.rmScoped;
  183. end;
  184. function TIocRegistration.IsTransient: Boolean;
  185. begin
  186. Result := fRegisterMode = TRegisterMode.rmTransient;
  187. end;
  188. function TIocRegistration.IsSingleton: Boolean;
  189. begin
  190. Result := fRegisterMode = TRegisterMode.rmSingleton;
  191. end;
  192. function TIocRegistration.IsScoped: Boolean;
  193. begin
  194. Result := fRegisterMode = TRegisterMode.rmScoped;
  195. end;
  196. { TIocContainer }
  197. class constructor TIocContainer.Create;
  198. begin
  199. GlobalInstance := TIocContainer.Create;
  200. end;
  201. class destructor TIocContainer.Destroy;
  202. begin
  203. if GlobalInstance <> nil then GlobalInstance.Free;
  204. inherited;
  205. end;
  206. function TIocContainer.AbstractFactory<T>(aClass: TClass): T;
  207. begin
  208. Result := fResolver.CreateInstance(aClass).AsType<T>;
  209. end;
  210. function TIocContainer.AbstractFactory<T> : T;
  211. begin
  212. Result := fResolver.CreateInstance(TClass(T)).AsType<T>;
  213. end;
  214. constructor TIocContainer.Create;
  215. begin
  216. fLogger := nil;
  217. fRegistrator := TIocRegistrator.Create;
  218. fInjector := TIocInjector.Create;
  219. fResolver := TIocResolver.Create(fRegistrator,fInjector);
  220. end;
  221. destructor TIocContainer.Destroy;
  222. begin
  223. fInjector.Free;
  224. fResolver.Free;
  225. fRegistrator.Free;
  226. fLogger := nil;
  227. inherited;
  228. end;
  229. function TIocContainer.InterfaceTypeInfo(const AGUID : TGUID) : PTypeInfo;
  230. var
  231. ctx : TRttiContext;
  232. rtype : TRttiType;
  233. rtypei : TRttiInterfaceType;
  234. begin
  235. for rtype in ctx.GetTypes do
  236. begin
  237. if rtype.TypeKind = TTypeKind.tkInterface then
  238. begin
  239. rtypei := (rtype as TRttiInterfaceType);
  240. if IsEqualGUID(rtypei.GUID,AGUID) then Exit(rtypei.Handle);
  241. end;
  242. end;
  243. Result := nil;
  244. end;
  245. function TIocContainer.IsRegistered<TInterface, TImplementation>(const aName: string): Boolean;
  246. begin
  247. Result := fRegistrator.IsRegistered<TInterface,TImplementation>(aName);
  248. end;
  249. function TIocContainer.IsRegistered<TInterface>(const aName: string): Boolean;
  250. begin
  251. Result := fRegistrator.IsRegistered<TInterface>(aName);
  252. end;
  253. function TIocContainer.RegisterType<TInterface, TImplementation>(const aName: string): TIocRegistration<TImplementation>;
  254. begin
  255. Result := fRegistrator.RegisterType<TInterface, TImplementation>(aName);
  256. end;
  257. function TIocContainer.RegisterType(aInterface: PTypeInfo; aImplementation: TClass; const aName: string): TIocRegistration;
  258. begin
  259. Result := fRegistrator.RegisterType(aInterface,aImplementation,aName);
  260. end;
  261. function TIocContainer.RegisterInstance<T>(const aName: string): TIocRegistration<T>;
  262. begin
  263. Result := fRegistrator.RegisterInstance<T>(aName);
  264. end;
  265. function TIocContainer.RegisterInstance(aTypeInfo : PTypeInfo; const aName : string = '') : TIocRegistration;
  266. begin
  267. Result := fRegistrator.RegisterInstance(aTypeInfo,aName);
  268. end;
  269. function TIocContainer.RegisterInstance<TInterface>(aInstance: TInterface; const aName: string): TIocRegistration;
  270. begin
  271. Result := fRegistrator.RegisterInstance<TInterface>(aInstance,aName);
  272. end;
  273. function TIocContainer.RegisterOptions<T>(aOptions: TOptions): TIocRegistration<T>;
  274. begin
  275. Result := fRegistrator.RegisterOptions<T>(aOptions).AsSingleton;
  276. end;
  277. function TIocContainer.RegisterOptions<T>(aOptions: TConfigureOptionsProc<T>): TIocRegistration<T>;
  278. var
  279. options : T;
  280. begin
  281. options := T.Create;
  282. aOptions(options);
  283. Result := Self.RegisterOptions<T>(options);
  284. end;
  285. function TIocContainer.Resolve(aServiceType: PTypeInfo; const aName: string): TValue;
  286. begin
  287. Result := fResolver.Resolve(aServiceType,aName);
  288. end;
  289. function TIocContainer.Resolve<T>(const aName : string = ''): T;
  290. begin
  291. Result := fResolver.Resolve<T>(aName);
  292. end;
  293. function TIocContainer.ResolveAll<T>(const aName : string = ''): TList<T>;
  294. begin
  295. Result := fResolver.ResolveAll<T>(aName);
  296. end;
  297. { TIocRegistrator }
  298. constructor TIocRegistrator.Create;
  299. begin
  300. fDependencies := TDictionary<string,TIocRegistration>.Create;
  301. end;
  302. destructor TIocRegistrator.Destroy;
  303. var
  304. reg : TIocRegistration;
  305. begin
  306. for reg in fDependencies.Values do
  307. begin
  308. if reg <> nil then
  309. begin
  310. //free singleton instances not interfaced
  311. if (reg is TIocRegistrationInstance) and (TIocRegistrationInstance(reg).IsSingleton) then TIocRegistrationInstance(reg).Instance.Free;
  312. reg.Free;
  313. end;
  314. end;
  315. fDependencies.Free;
  316. inherited;
  317. end;
  318. function TIocRegistrator.GetKey(aPInfo : PTypeInfo; const aName : string = ''): string;
  319. begin
  320. {$IFDEF NEXTGEN}
  321. Result := aPInfo.Name.ToString;
  322. {$ELSE}
  323. Result := string(aPInfo.Name);
  324. {$ENDIF}
  325. if not aName.IsEmpty then Result := Result + '.' + aName.ToLower;
  326. end;
  327. function TIocRegistrator.IsRegistered<TInterface, TImplementation>(const aName: string): Boolean;
  328. var
  329. key : string;
  330. reg : TIocRegistration;
  331. begin
  332. Result := False;
  333. key := GetKey(TypeInfo(TInterface),aName);
  334. if fDependencies.TryGetValue(key,reg) then
  335. begin
  336. if reg.&Implementation = TImplementation then Result := True;
  337. end
  338. end;
  339. function TIocRegistrator.IsRegistered<TInterface>(const aName: string): Boolean;
  340. var
  341. key : string;
  342. reg : TIocRegistration;
  343. begin
  344. Result := False;
  345. key := GetKey(TypeInfo(TInterface),aName);
  346. if fDependencies.TryGetValue(key,reg) then
  347. begin
  348. //if (reg is TIocRegistrationInterface) and (TIocRegistrationInterface(reg).Instance <> nil) then Result := True;
  349. if reg is TIocRegistrationInterface then Result := True;
  350. end
  351. end;
  352. function TIocRegistrator.RegisterInstance<T>(const aName: string): TIocRegistration<T>;
  353. var
  354. reg : TIocRegistration;
  355. begin
  356. reg := RegisterInstance(TypeInfo(T),aName);
  357. Result := TIocRegistration<T>.Create(reg);
  358. end;
  359. function TIocRegistrator.RegisterInstance<TInterface>(aInstance: TInterface; const aName: string): TIocRegistration;
  360. var
  361. key : string;
  362. tpinfo : PTypeInfo;
  363. begin
  364. tpinfo := TypeInfo(TInterface);
  365. key := GetKey(tpinfo,aName);
  366. if fDependencies.TryGetValue(key,Result) then
  367. begin
  368. if Result.&Implementation = tpinfo.TypeData.ClassType then raise EIocRegisterError.Create('Implementation is already registered!');
  369. end
  370. else
  371. begin
  372. Result := TIocRegistrationInterface.Create;
  373. Result.IntfInfo := tpinfo;
  374. TIocRegistrationInterface(Result).Instance := aInstance;
  375. //reg.Instance := T.Create;
  376. fDependencies.Add(key,Result);
  377. end;
  378. end;
  379. function TIocRegistrator.RegisterInstance(aTypeInfo : PTypeInfo; const aName : string = '') : TIocRegistration;
  380. var
  381. key : string;
  382. begin
  383. key := GetKey(aTypeInfo,aName);
  384. if fDependencies.TryGetValue(key,Result) then
  385. begin
  386. if Result.&Implementation = aTypeInfo.TypeData.ClassType then raise EIocRegisterError.Create('Implementation is already registered!');
  387. end
  388. else
  389. begin
  390. Result := TIocRegistrationInstance.Create;
  391. Result.IntfInfo := aTypeInfo;
  392. Result.&Implementation := aTypeInfo.TypeData.ClassType;
  393. //reg.Instance := T.Create;
  394. fDependencies.Add(key,Result);
  395. end;
  396. end;
  397. function TIocRegistrator.RegisterOptions<T>(aOptions: T): TIocRegistration<T>;
  398. var
  399. pInfo : PTypeInfo;
  400. key : string;
  401. reg : TIocRegistration;
  402. begin
  403. pInfo := TypeInfo(IOptions<T>);
  404. key := GetKey(pInfo,'');
  405. if fDependencies.TryGetValue(key,reg) then
  406. begin
  407. if reg.&Implementation = aOptions.ClassType then raise EIocRegisterError.Create('Implementation for this interface is already registered!');
  408. end
  409. else
  410. begin
  411. reg := TIocRegistrationInterface.Create;
  412. reg.IntfInfo := pInfo;
  413. reg.&Implementation := aOptions.ClassType;
  414. TIocRegistrationInterface(reg).Instance := TOptionValue<T>.Create(aOptions);
  415. fDependencies.Add(key,reg);
  416. end;
  417. Result := TIocRegistration<T>.Create(reg);
  418. end;
  419. function TIocRegistrator.RegisterType<TInterface, TImplementation>(const aName: string): TIocRegistration<TImplementation>;
  420. var
  421. reg : TIocRegistration;
  422. begin
  423. reg := RegisterType(TypeInfo(TInterface),TImplementation,aName);
  424. Result := TIocRegistration<TImplementation>.Create(reg);
  425. end;
  426. function TIocRegistrator.RegisterType(aTypeInfo : PTypeInfo; aImplementation : TClass; const aName : string = '') : TIocRegistration;
  427. var
  428. key : string;
  429. begin
  430. key := GetKey(aTypeInfo,aName);
  431. if fDependencies.TryGetValue(key,Result) then
  432. begin
  433. if Result.&Implementation = aImplementation then raise EIocRegisterError.Create('Implementation for this interface is already registered!')
  434. else Key := key + '#' + TGUID.NewGuid.ToString;
  435. end;
  436. Result := TIocRegistrationInterface.Create;
  437. Result.IntfInfo := aTypeInfo;
  438. Result.&Implementation := aImplementation;
  439. fDependencies.Add(key,Result);
  440. end;
  441. { TIocResolver }
  442. constructor TIocResolver.Create(aRegistrator : TIocRegistrator; aInjector : TIocInjector);
  443. begin
  444. fRegistrator := aRegistrator;
  445. fInjector := aInjector;
  446. end;
  447. function TIocResolver.CreateInstance(aClass: TClass): TValue;
  448. var
  449. ctx : TRttiContext;
  450. rtype : TRttiType;
  451. rmethod : TRttiMethod;
  452. rParam : TRttiParameter;
  453. value : TValue;
  454. values : TArray<TValue>;
  455. begin
  456. Result := nil;
  457. rtype := ctx.GetType(aClass);
  458. if rtype = nil then Exit;
  459. for rmethod in TRttiInstanceType(rtype).GetMethods do
  460. begin
  461. if rmethod.IsConstructor then
  462. begin
  463. //if create don't have parameters
  464. if Length(rmethod.GetParameters) = 0 then
  465. begin
  466. Result := rmethod.Invoke(TRttiInstanceType(rtype).MetaclassType,[]);
  467. Break;
  468. end
  469. else
  470. begin
  471. for rParam in rmethod.GetParameters do
  472. begin
  473. value := Resolve(rParam.ParamType.Handle);
  474. values := values + [value];
  475. end;
  476. Result := rmethod.Invoke(TRttiInstanceType(rtype).MetaclassType,values);
  477. Break;
  478. end;
  479. end;
  480. end;
  481. end;
  482. function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''): TValue;
  483. var
  484. key : string;
  485. reg : TIocRegistration;
  486. intf : IInterface;
  487. begin
  488. Result := nil;
  489. reg := nil;
  490. key := fRegistrator.GetKey(aServiceType,aName);
  491. if not fRegistrator.Dependencies.TryGetValue(key,reg) then raise EIocResolverError.CreateFmt('Type "%s" not registered for IOC!',[aServiceType.Name]);
  492. //if is singleton return already instance if exists
  493. if reg.IsSingleton then
  494. begin
  495. if reg is TIocRegistrationInterface then
  496. begin
  497. if TIocRegistrationInterface(reg).Instance <> nil then
  498. begin
  499. if TIocRegistrationInterface(reg).Instance.QueryInterface(GetTypeData(aServiceType).Guid,intf) <> 0 then raise EIocResolverError.CreateFmt('Implementation for "%s" not registered!',[aServiceType.Name]);
  500. TValue.Make(@intf,aServiceType,Result);
  501. Exit;
  502. end;
  503. end
  504. else
  505. begin
  506. if TIocRegistrationInstance(reg).Instance <> nil then
  507. begin
  508. Result := TIocRegistrationInstance(reg).Instance;
  509. Exit;
  510. end;
  511. end;
  512. end;
  513. //instance not created yet
  514. if reg.&Implementation = nil then raise EIocResolverError.CreateFmt('Implemention for "%s" not defined!',[aServiceType.Name]);
  515. //use activator if assigned
  516. if reg is TIocRegistrationInterface then
  517. begin
  518. if Assigned(reg.ActivatorDelegate) then TIocRegistrationInterface(reg).Instance := reg.ActivatorDelegate().AsInterface
  519. else TIocRegistrationInterface(reg).Instance := CreateInstance(reg.&Implementation).AsInterface;
  520. 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]);
  521. TValue.Make(@intf,aServiceType,Result);
  522. end
  523. else
  524. begin
  525. if Assigned(reg.ActivatorDelegate) then TIocRegistrationInstance(reg).Instance := reg.ActivatorDelegate().AsObject
  526. else
  527. begin
  528. TIocRegistrationInstance(reg).Instance := CreateInstance(reg.&Implementation).AsObject;
  529. end;
  530. Result := TIocRegistrationInstance(reg).Instance;
  531. end;
  532. end;
  533. function TIocResolver.Resolve<T>(const aName : string = ''): T;
  534. var
  535. pInfo : PTypeInfo;
  536. begin
  537. Result := Default(T);
  538. pInfo := TypeInfo(T);
  539. Result := Resolve(pInfo,aName).AsType<T>;
  540. end;
  541. function TIocResolver.ResolveAll<T>(const aName : string = '') : TList<T>;
  542. var
  543. pInfo : PTypeInfo;
  544. reg : TIocRegistration;
  545. pair : TPair<string,TIocRegistration>;
  546. begin
  547. Result := TList<T>.Create;
  548. pInfo := TypeInfo(T);
  549. for pair in fRegistrator.Dependencies.ToArray do
  550. begin
  551. reg := pair.Value;
  552. //var a := pair.Key;
  553. if reg.IntfInfo = pInfo then Self.Resolve(pInfo,aName);
  554. end;
  555. end;
  556. { TIocRegistration<T> }
  557. function TIocRegistration<T>.AsScoped: TIocRegistration<T>;
  558. begin
  559. Result := Self;
  560. fRegistration.AsScoped;
  561. end;
  562. function TIocRegistration<T>.AsSingleton: TIocRegistration<T>;
  563. begin
  564. Result := Self;
  565. fRegistration.AsSingleton;
  566. end;
  567. function TIocRegistration<T>.AsTransient: TIocRegistration<T>;
  568. begin
  569. Result := Self;
  570. fRegistration.AsTransient;
  571. end;
  572. constructor TIocRegistration<T>.Create(aRegistration: TIocRegistration);
  573. begin
  574. fRegistration := aRegistration;
  575. end;
  576. function TIocRegistration<T>.DelegateTo(aDelegate: TActivatorDelegate<T>): TIocRegistration<T>;
  577. begin
  578. Result := Self;
  579. fRegistration.ActivatorDelegate := function: TValue
  580. begin
  581. Result := TValue.From<T>(aDelegate);
  582. end;
  583. end;
  584. end.