Quick.IOC.pas 20 KB

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