Quick.IOC.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  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 : 10/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. end;
  124. TIocContainer = class(TInterfacedObject,IIocContainer)
  125. private
  126. fRegistrator : TIocRegistrator;
  127. fResolver : TIocResolver;
  128. fInjector : TIocInjector;
  129. fLogger : ILogger;
  130. function InterfaceTypeInfo(const AGUID : TGUID) : PTypeInfo;
  131. class var
  132. GlobalInstance: TIocContainer;
  133. protected
  134. class constructor Create;
  135. class destructor Destroy;
  136. public
  137. constructor Create;
  138. destructor Destroy; override;
  139. function IsRegistered<TInterface: IInterface; TImplementation: class>(const aName: string): Boolean; overload;
  140. function IsRegistered<TInterface : IInterface>(const aName: string): Boolean; overload;
  141. function RegisterType<TInterface: IInterface; TImplementation: class>(const aName : string = '') : TIocRegistration<TImplementation>; overload;
  142. function RegisterType(aInterface: PTypeInfo; aImplementation : TClass; const aName : string = '') : TIocRegistration; overload;
  143. function RegisterInstance<T : class>(const aName: string = ''): TIocRegistration<T>; overload;
  144. function RegisterInstance(aTypeInfo : PTypeInfo; const aName : string = '') : TIocRegistration; overload;
  145. function RegisterInstance<TInterface : IInterface>(aInstance : TInterface; const aName : string = '') : TIocRegistration; overload;
  146. function RegisterOptions<T : TOptions>(aOptions : TOptions) : TIocRegistration<T>; overload;
  147. function RegisterOptions<T : TOptions>(aOptions : TConfigureOptionsProc<T>) : TIocRegistration<T>; overload;
  148. function Resolve<T>(const aName : string = ''): T; overload;
  149. function Resolve(aServiceType: PTypeInfo; const aName : string = ''): TValue; overload;
  150. function AbstractFactory<T : class, constructor>(aClass : TClass) : T; overload;
  151. function AbstractFactory<T : class, constructor> : T; overload;
  152. end;
  153. EIocRegisterError = class(Exception);
  154. EIocResolverError = class(Exception);
  155. //singleton global instance
  156. function GlobalContainer: TIocContainer;
  157. implementation
  158. function GlobalContainer: TIocContainer;
  159. begin
  160. Result := TIocContainer.GlobalInstance;
  161. end;
  162. { TIocRegistration }
  163. constructor TIocRegistration.Create;
  164. begin
  165. fRegisterMode := TRegisterMode.rmTransient;
  166. end;
  167. function TIocRegistration.AsTransient: TIocRegistration;
  168. begin
  169. Result := Self;
  170. fRegisterMode := TRegisterMode.rmTransient;
  171. end;
  172. function TIocRegistration.AsSingleton : TIocRegistration;
  173. begin
  174. Result := Self;
  175. fRegisterMode := TRegisterMode.rmSingleton;
  176. end;
  177. function TIocRegistration.AsScoped: TIocRegistration;
  178. begin
  179. Result := Self;
  180. fRegisterMode := TRegisterMode.rmScoped;
  181. end;
  182. function TIocRegistration.IsTransient: Boolean;
  183. begin
  184. Result := fRegisterMode = TRegisterMode.rmTransient;
  185. end;
  186. function TIocRegistration.IsSingleton: Boolean;
  187. begin
  188. Result := fRegisterMode = TRegisterMode.rmSingleton;
  189. end;
  190. function TIocRegistration.IsScoped: Boolean;
  191. begin
  192. Result := fRegisterMode = TRegisterMode.rmScoped;
  193. end;
  194. { TIocContainer }
  195. class constructor TIocContainer.Create;
  196. begin
  197. GlobalInstance := TIocContainer.Create;
  198. end;
  199. class destructor TIocContainer.Destroy;
  200. begin
  201. if GlobalInstance <> nil then GlobalInstance.Free;
  202. inherited;
  203. end;
  204. function TIocContainer.AbstractFactory<T>(aClass: TClass): T;
  205. begin
  206. Result := fResolver.CreateInstance(aClass).AsType<T>;
  207. end;
  208. function TIocContainer.AbstractFactory<T> : T;
  209. begin
  210. Result := fResolver.CreateInstance(TClass(T)).AsType<T>;
  211. end;
  212. constructor TIocContainer.Create;
  213. begin
  214. fLogger := nil;
  215. fRegistrator := TIocRegistrator.Create;
  216. fInjector := TIocInjector.Create;
  217. fResolver := TIocResolver.Create(fRegistrator,fInjector);
  218. end;
  219. destructor TIocContainer.Destroy;
  220. begin
  221. fInjector.Free;
  222. fResolver.Free;
  223. fRegistrator.Free;
  224. fLogger := nil;
  225. inherited;
  226. end;
  227. function TIocContainer.InterfaceTypeInfo(const AGUID : TGUID) : PTypeInfo;
  228. var
  229. ctx : TRttiContext;
  230. rtype : TRttiType;
  231. rtypei : TRttiInterfaceType;
  232. begin
  233. ctx := TRttiContext.Create;
  234. try
  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. finally
  244. ctx.Free;
  245. end;
  246. Result := nil;
  247. end;
  248. function TIocContainer.IsRegistered<TInterface, TImplementation>(const aName: string): Boolean;
  249. begin
  250. Result := fRegistrator.IsRegistered<TInterface,TImplementation>(aName);
  251. end;
  252. function TIocContainer.IsRegistered<TInterface>(const aName: string): Boolean;
  253. begin
  254. Result := fRegistrator.IsRegistered<TInterface>(aName);
  255. end;
  256. function TIocContainer.RegisterType<TInterface, TImplementation>(const aName: string): TIocRegistration<TImplementation>;
  257. begin
  258. Result := fRegistrator.RegisterType<TInterface, TImplementation>(aName);
  259. end;
  260. function TIocContainer.RegisterType(aInterface: PTypeInfo; aImplementation: TClass; const aName: string): TIocRegistration;
  261. begin
  262. Result := fRegistrator.RegisterType(aInterface,aImplementation,aName);
  263. end;
  264. function TIocContainer.RegisterInstance<T>(const aName: string): TIocRegistration<T>;
  265. begin
  266. Result := fRegistrator.RegisterInstance<T>(aName);
  267. end;
  268. function TIocContainer.RegisterInstance(aTypeInfo : PTypeInfo; const aName : string = '') : TIocRegistration;
  269. begin
  270. Result := fRegistrator.RegisterInstance(aTypeInfo,aName);
  271. end;
  272. function TIocContainer.RegisterInstance<TInterface>(aInstance: TInterface; const aName: string): TIocRegistration;
  273. begin
  274. Result := fRegistrator.RegisterInstance<TInterface>(aInstance,aName);
  275. end;
  276. function TIocContainer.RegisterOptions<T>(aOptions: TOptions): TIocRegistration<T>;
  277. begin
  278. Result := fRegistrator.RegisterOptions<T>(aOptions).AsSingleton;
  279. end;
  280. function TIocContainer.RegisterOptions<T>(aOptions: TConfigureOptionsProc<T>): TIocRegistration<T>;
  281. var
  282. options : T;
  283. begin
  284. options := T.Create;
  285. aOptions(options);
  286. Result := Self.RegisterOptions<T>(options);
  287. end;
  288. function TIocContainer.Resolve(aServiceType: PTypeInfo; const aName: string): TValue;
  289. begin
  290. Result := fResolver.Resolve(aServiceType,aName);
  291. end;
  292. function TIocContainer.Resolve<T>(const aName : string = ''): T;
  293. begin
  294. Result := fResolver.Resolve<T>(aName);
  295. end;
  296. { TIocRegistrator }
  297. constructor TIocRegistrator.Create;
  298. begin
  299. fDependencies := TDictionary<string,TIocRegistration>.Create;
  300. end;
  301. destructor TIocRegistrator.Destroy;
  302. var
  303. reg : TIocRegistration;
  304. begin
  305. for reg in fDependencies.Values do
  306. begin
  307. if reg <> nil then
  308. begin
  309. //free singleton instances not interfaced
  310. if (reg is TIocRegistrationInstance) and (TIocRegistrationInstance(reg).IsSingleton) then TIocRegistrationInstance(reg).Instance.Free;
  311. reg.Free;
  312. end;
  313. end;
  314. fDependencies.Free;
  315. inherited;
  316. end;
  317. function TIocRegistrator.GetKey(aPInfo : PTypeInfo; const aName : string = ''): string;
  318. begin
  319. {$IFDEF NEXTGEN}
  320. Result := aPInfo.Name.ToString;
  321. {$ELSE}
  322. Result := string(aPInfo.Name);
  323. {$ENDIF}
  324. if not aName.IsEmpty then Result := Result + '.' + aName.ToLower;
  325. end;
  326. function TIocRegistrator.IsRegistered<TInterface, TImplementation>(const aName: string): Boolean;
  327. var
  328. key : string;
  329. reg : TIocRegistration;
  330. begin
  331. Result := False;
  332. key := GetKey(TypeInfo(TInterface),aName);
  333. if fDependencies.TryGetValue(key,reg) then
  334. begin
  335. if reg.&Implementation = TImplementation then Result := True;
  336. end
  337. end;
  338. function TIocRegistrator.IsRegistered<TInterface>(const aName: string): Boolean;
  339. var
  340. key : string;
  341. reg : TIocRegistration;
  342. begin
  343. Result := False;
  344. key := GetKey(TypeInfo(TInterface),aName);
  345. if fDependencies.TryGetValue(key,reg) then
  346. begin
  347. if (reg is TIocRegistrationInterface) and (TIocRegistrationInterface(reg).Instance <> nil) then Result := True;
  348. end
  349. end;
  350. function TIocRegistrator.RegisterInstance<T>(const aName: string): TIocRegistration<T>;
  351. var
  352. reg : TIocRegistration;
  353. begin
  354. reg := RegisterInstance(TypeInfo(T),aName);
  355. Result := TIocRegistration<T>.Create(reg);
  356. end;
  357. function TIocRegistrator.RegisterInstance<TInterface>(aInstance: TInterface; const aName: string): TIocRegistration;
  358. var
  359. key : string;
  360. tpinfo : PTypeInfo;
  361. begin
  362. tpinfo := TypeInfo(TInterface);
  363. key := GetKey(tpinfo,aName);
  364. if fDependencies.TryGetValue(key,Result) then
  365. begin
  366. if Result.&Implementation = tpinfo.TypeData.ClassType then raise EIocRegisterError.Create('Implementation is already registered!');
  367. end
  368. else
  369. begin
  370. Result := TIocRegistrationInterface.Create;
  371. Result.IntfInfo := tpinfo;
  372. TIocRegistrationInterface(Result).Instance := aInstance;
  373. //reg.Instance := T.Create;
  374. fDependencies.Add(key,Result);
  375. end;
  376. end;
  377. function TIocRegistrator.RegisterInstance(aTypeInfo : PTypeInfo; const aName : string = '') : TIocRegistration;
  378. var
  379. key : string;
  380. begin
  381. key := GetKey(aTypeInfo,aName);
  382. if fDependencies.TryGetValue(key,Result) then
  383. begin
  384. if Result.&Implementation = aTypeInfo.TypeData.ClassType then raise EIocRegisterError.Create('Implementation is already registered!');
  385. end
  386. else
  387. begin
  388. Result := TIocRegistrationInstance.Create;
  389. Result.IntfInfo := aTypeInfo;
  390. Result.&Implementation := aTypeInfo.TypeData.ClassType;
  391. //reg.Instance := T.Create;
  392. fDependencies.Add(key,Result);
  393. end;
  394. end;
  395. function TIocRegistrator.RegisterOptions<T>(aOptions: T): TIocRegistration<T>;
  396. var
  397. pInfo : PTypeInfo;
  398. key : string;
  399. reg : TIocRegistration;
  400. begin
  401. pInfo := TypeInfo(IOptions<T>);
  402. key := GetKey(pInfo,'');
  403. if fDependencies.TryGetValue(key,reg) then
  404. begin
  405. if reg.&Implementation = aOptions.ClassType then raise EIocRegisterError.Create('Implementation for this interface is already registered!');
  406. end
  407. else
  408. begin
  409. reg := TIocRegistrationInterface.Create;
  410. reg.IntfInfo := pInfo;
  411. reg.&Implementation := aOptions.ClassType;
  412. TIocRegistrationInterface(reg).Instance := TOptionValue<T>.Create(aOptions);
  413. fDependencies.Add(key,reg);
  414. end;
  415. Result := TIocRegistration<T>.Create(reg);
  416. end;
  417. function TIocRegistrator.RegisterType<TInterface, TImplementation>(const aName: string): TIocRegistration<TImplementation>;
  418. var
  419. reg : TIocRegistration;
  420. begin
  421. reg := RegisterType(TypeInfo(TInterface),TImplementation,aName);
  422. Result := TIocRegistration<TImplementation>.Create(reg);
  423. end;
  424. function TIocRegistrator.RegisterType(aTypeInfo : PTypeInfo; aImplementation : TClass; const aName : string = '') : TIocRegistration;
  425. var
  426. key : string;
  427. begin
  428. key := GetKey(aTypeInfo,aName);
  429. if fDependencies.TryGetValue(key,Result) then
  430. begin
  431. if Result.&Implementation = aImplementation then raise EIocRegisterError.Create('Implementation for this interface is already registered!');
  432. end
  433. else
  434. begin
  435. Result := TIocRegistrationInterface.Create;
  436. Result.IntfInfo := aTypeInfo;
  437. Result.&Implementation := aImplementation;
  438. fDependencies.Add(key,Result);
  439. end;
  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. ctx := TRttiContext.Create;
  458. try
  459. rtype := ctx.GetType(aClass);
  460. if rtype = nil then Exit;
  461. for rmethod in TRttiInstanceType(rtype).GetMethods do
  462. begin
  463. if rmethod.IsConstructor then
  464. begin
  465. //if create don't have parameters
  466. if Length(rmethod.GetParameters) = 0 then
  467. begin
  468. Result := rmethod.Invoke(TRttiInstanceType(rtype).MetaclassType,[]);
  469. Break;
  470. end
  471. else
  472. begin
  473. for rParam in rmethod.GetParameters do
  474. begin
  475. value := Resolve(rParam.ParamType.Handle);
  476. values := values + [value];
  477. end;
  478. Result := rmethod.Invoke(TRttiInstanceType(rtype).MetaclassType,values);
  479. Break;
  480. end;
  481. end;
  482. end;
  483. finally
  484. ctx.Free;
  485. end;
  486. end;
  487. function TIocResolver.Resolve(aServiceType: PTypeInfo; const aName : string = ''): TValue;
  488. var
  489. key : string;
  490. reg : TIocRegistration;
  491. intf : IInterface;
  492. begin
  493. Result := nil;
  494. reg := nil;
  495. key := fRegistrator.GetKey(aServiceType,aName);
  496. if not fRegistrator.Dependencies.TryGetValue(key,reg) then raise EIocResolverError.CreateFmt('Type "%s" not register for IOC!',[aServiceType.Name]);
  497. //if is singleton return already instance if exists
  498. if reg.IsSingleton then
  499. begin
  500. if reg is TIocRegistrationInterface then
  501. begin
  502. if TIocRegistrationInterface(reg).Instance <> nil then
  503. begin
  504. if TIocRegistrationInterface(reg).Instance.QueryInterface(GetTypeData(aServiceType).Guid,intf) <> 0 then raise EIocResolverError.CreateFmt('Implementation for "%s" not registered!',[aServiceType.Name]);
  505. TValue.Make(@intf,aServiceType,Result);
  506. Exit;
  507. end;
  508. end
  509. else
  510. begin
  511. if TIocRegistrationInstance(reg).Instance <> nil then
  512. begin
  513. Result := TIocRegistrationInstance(reg).Instance;
  514. Exit;
  515. end;
  516. end;
  517. end;
  518. //instance not created yet
  519. if reg.&Implementation = nil then raise EIocResolverError.CreateFmt('Implemention for "%s" not defined!',[aServiceType.Name]);
  520. //use activator if assigned
  521. if reg is TIocRegistrationInterface then
  522. begin
  523. if Assigned(reg.ActivatorDelegate) then TIocRegistrationInterface(reg).Instance := reg.ActivatorDelegate().AsInterface
  524. else TIocRegistrationInterface(reg).Instance := CreateInstance(reg.&Implementation).AsInterface;
  525. 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]);
  526. TValue.Make(@intf,aServiceType,Result);
  527. end
  528. else
  529. begin
  530. if Assigned(reg.ActivatorDelegate) then TIocRegistrationInstance(reg).Instance := reg.ActivatorDelegate().AsObject
  531. else
  532. begin
  533. TIocRegistrationInstance(reg).Instance := CreateInstance(reg.&Implementation).AsObject;
  534. end;
  535. Result := TIocRegistrationInstance(reg).Instance;
  536. end;
  537. end;
  538. function TIocResolver.Resolve<T>(const aName : string = ''): T;
  539. var
  540. pInfo : PTypeInfo;
  541. begin
  542. Result := Default(T);
  543. pInfo := TypeInfo(T);
  544. Result := Resolve(pInfo,aName).AsType<T>;
  545. end;
  546. { TIocRegistration<T> }
  547. function TIocRegistration<T>.AsScoped: TIocRegistration<T>;
  548. begin
  549. Result := Self;
  550. fRegistration.AsScoped;
  551. end;
  552. function TIocRegistration<T>.AsSingleton: TIocRegistration<T>;
  553. begin
  554. Result := Self;
  555. fRegistration.AsSingleton;
  556. end;
  557. function TIocRegistration<T>.AsTransient: TIocRegistration<T>;
  558. begin
  559. Result := Self;
  560. fRegistration.AsTransient;
  561. end;
  562. constructor TIocRegistration<T>.Create(aRegistration: TIocRegistration);
  563. begin
  564. fRegistration := aRegistration;
  565. end;
  566. function TIocRegistration<T>.DelegateTo(aDelegate: TActivatorDelegate<T>): TIocRegistration<T>;
  567. begin
  568. Result := Self;
  569. fRegistration.ActivatorDelegate := function: TValue
  570. begin
  571. Result := TValue.From<T>(aDelegate);
  572. end;
  573. end;
  574. end.