IOCdemo.dpr 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. program IOCdemo;
  2. {$APPTYPE CONSOLE}
  3. {$R *.res}
  4. uses
  5. System.SysUtils,
  6. Quick.Commons,
  7. Quick.Console,
  8. Quick.IOC;
  9. type
  10. IMathService = interface
  11. ['{E8BEE282-3828-4F27-869D-C808296F8CA2}']
  12. procedure IncNumsOperations;
  13. function NumOperations : Integer;
  14. end;
  15. ISumService = interface(IMathService)
  16. ['{7580F5F6-0132-49F3-A22A-A2E93E53E8A7}']
  17. function Sum(a, b : Integer) : Integer;
  18. end;
  19. IMultService = interface(IMathService)
  20. ['{56772C4B-70AF-4BB7-9DFE-E2D67912DDC1}']
  21. function Mult(a, b : Integer) : Integer;
  22. end;
  23. TMathService = class(TInterfacedObject,IMathService)
  24. private
  25. fNumOperations : Integer;
  26. public
  27. constructor Create;
  28. procedure IncNumsOperations;
  29. function NumOperations : Integer;
  30. end;
  31. TSumService = class(TMathService,ISumService)
  32. public
  33. function Sum(a, b : Integer) : Integer;
  34. end;
  35. TMultService = class(TMathService,IMultService)
  36. public
  37. function Mult(a, b : Integer) : Integer;
  38. end;
  39. IBigService = interface
  40. ['{AE7E7617-02BD-48C9-A370-49566A563C38}']
  41. function GetNumOperations : Integer;
  42. function Sum(a, b : Integer) : Integer;
  43. function Mult(a, b : Integer) : Integer;
  44. function SumService : ISumService;
  45. function MultService : IMultService;
  46. property NumOperations : Integer read GetNumOperations;
  47. end;
  48. TBigService = class(TInterfacedObject,IBigService)
  49. private
  50. fSumService : ISumService;
  51. fMultService : IMultService;
  52. fNumOperations : Integer;
  53. function GetNumOperations : Integer;
  54. procedure IncNumOperations;
  55. public
  56. constructor Create(aSumService : ISumService; aMultService : IMultService);
  57. function Sum(a, b : Integer) : Integer;
  58. function Mult(a, b : Integer) : Integer;
  59. function SumService : ISumService;
  60. function MultService : IMultService;
  61. property NumOperations : Integer read GetNumOperations;
  62. end;
  63. TDivideService = class
  64. private
  65. fNumOperations : Integer;
  66. fRound : Boolean;
  67. public
  68. constructor Create(aRound : Boolean);
  69. property NumOperations : Integer read fNumOperations;
  70. function Divide(a,b : Integer) : Integer;
  71. end;
  72. { TSumService }
  73. function TSumService.Sum(a, b: Integer): Integer;
  74. begin
  75. Result := a + b;
  76. IncNumsOperations;
  77. end;
  78. { TMultService }
  79. function TMultService.Mult(a, b: Integer): Integer;
  80. begin
  81. Result := a * b;
  82. IncNumsOperations;
  83. end;
  84. { TBigService }
  85. constructor TBigService.Create(aSumService: ISumService; aMultService: IMultService);
  86. begin
  87. fSumService := aSumService;
  88. fMultService := aMultService;
  89. end;
  90. function TBigService.Sum(a, b: Integer): Integer;
  91. begin
  92. Result := fSumService.Sum(a,b);
  93. IncNumOperations;
  94. end;
  95. function TBigService.SumService: ISumService;
  96. begin
  97. Result := fSumService;
  98. end;
  99. function TBigService.GetNumOperations: Integer;
  100. begin
  101. Result := fNumOperations;
  102. end;
  103. procedure TBigService.IncNumOperations;
  104. begin
  105. Inc(fNumOperations);
  106. end;
  107. function TBigService.Mult(a, b: Integer): Integer;
  108. begin
  109. Result := fMultService.Mult(a,b);
  110. IncNumOperations;
  111. end;
  112. function TBigService.MultService: IMultService;
  113. begin
  114. Result := fMultService;
  115. end;
  116. var
  117. iocContainer : TIocContainer;
  118. sumservice : ISumService;
  119. multservice : IMultService;
  120. bigservice : IBigService;
  121. divideservice : TDivideService;
  122. res : Integer;
  123. i : Integer;
  124. times : Integer;
  125. numoperations : Integer;
  126. { TMathService }
  127. constructor TMathService.Create;
  128. begin
  129. fNumOperations := 0;
  130. end;
  131. procedure TMathService.IncNumsOperations;
  132. begin
  133. Inc(fNumOperations);
  134. end;
  135. function TMathService.NumOperations: Integer;
  136. begin
  137. Result := fNumOperations;
  138. end;
  139. { TDivideService }
  140. constructor TDivideService.Create(aRound : Boolean);
  141. begin
  142. fNumOperations := 0;
  143. fRound := aRound;
  144. end;
  145. function TDivideService.Divide(a, b: Integer): Integer;
  146. begin
  147. if fRound then Result := Round(a / b)
  148. else Result := Trunc(a / b);
  149. Inc(fNumOperations);
  150. end;
  151. begin
  152. try
  153. ReportMemoryLeaksOnShutdown := True;
  154. iocContainer := TIocContainer.Create;
  155. iocContainer.RegisterType<ISumService,TSumService>.AsSingleTon.DelegateTo(function : TSumService
  156. begin
  157. Result := TSumService.Create;
  158. end);
  159. iocContainer.RegisterType<IMultService,TMultService>.AsTransient;
  160. iocContainer.RegisterType<IBigService,TBigService>('one').AsSingleTon;
  161. iocContainer.RegisterType<IBigService,TBigService>('other').AsTransient;
  162. iocContainer.RegisterInstance<TDivideService>('one').AsSingleton.DelegateTo(function : TDivideService
  163. begin
  164. Result := TDivideService.Create(True);
  165. end);
  166. iocContainer.RegisterInstance<TDivideService>('other').AsTransient.DelegateTo(function : TDivideService
  167. begin
  168. Result := TDivideService.Create(True);
  169. end);
  170. times := 100;
  171. res := 0;
  172. //test1: class injection as singleton
  173. for i := 1 to times do
  174. begin
  175. sumservice := iocContainer.Resolve<ISumService>;
  176. res := sumservice.Sum(2,2);
  177. end;
  178. if sumservice.NumOperations = times then cout('Test1: Class injection as Singleton test ok',etSuccess)
  179. else cout('Test1: Class injection as Singleton test error',etError);
  180. cout('SumService.Sum = %d (calls: %d)',[res,sumservice.NumOperations],etInfo);
  181. //test2: class injection as transient
  182. for i := 1 to times do
  183. begin
  184. multservice := iocContainer.Resolve<IMultService>;
  185. res := multservice.Mult(2,4);
  186. end;
  187. if multservice.NumOperations = 1 then cout('Test2: Class injection as Transient test ok',etSuccess)
  188. else cout('Test2: Class injection as Transient test error',etError);
  189. cout('MultService.Mult = %d (calls: %d)',[res,multservice.NumOperations],etInfo);
  190. //test3: constructor injection as singleton
  191. for i := 1 to times do
  192. begin
  193. bigservice := iocContainer.Resolve<IBigService>('one');
  194. res := bigservice.Sum(2,2);
  195. end;
  196. if bigservice.NumOperations = times then cout('Test3: Constructor injection as Singleton test ok',etSuccess)
  197. else cout('Test3: Constructor injection as Singleton test error',etError);
  198. cout('BigService.Sum = %d (calls: %d to BigService / calls: %d to SumService (as singleton))',[res,bigservice.NumOperations,bigservice.sumservice.NumOperations],etInfo);
  199. //test4: constructor injection as transient
  200. for i := 1 to times do
  201. begin
  202. bigservice := iocContainer.Resolve<IBigService>('other');
  203. res := bigservice.Mult(2,4);
  204. end;
  205. if bigservice.NumOperations = 1 then cout('Test4: Constructor injection as Transient test ok',etSuccess)
  206. else cout('Test4: Constructor injection as Transient test error',etError);
  207. cout('BigService.Mult = %d (calls: %d to BigService / calls: %d to MultService (as transient))',[res,bigservice.NumOperations,bigservice.multservice.NumOperations],etInfo);
  208. //test5: class instance injection as singleton
  209. for i := 1 to times do
  210. begin
  211. divideservice := iocContainer.Resolve<TDivideService>('one');
  212. res := divideservice.Divide(100,2);
  213. end;
  214. if divideservice.NumOperations = times then cout('Test5: Class instance injection as Singleton test ok',etSuccess)
  215. else cout('Test5: Class instance injection as Singleton test error',etError);
  216. cout('DivideService.Divide = %d (calls: %d)',[res,divideservice.NumOperations],etInfo);
  217. //test6: class instance injection as transient
  218. for i := 1 to times do
  219. begin
  220. divideservice := iocContainer.Resolve<TDivideService>('other');
  221. res := divideservice.Divide(100,2);
  222. numoperations := divideservice.NumOperations;
  223. //transient instances must be manual free
  224. divideservice.Free;
  225. end;
  226. if numoperations = 1 then cout('Test6: Class instance injection as Transient test ok',etSuccess)
  227. else cout('Test6: Class instance injection as Transient test error',etError);
  228. cout('DivideService.Divide = %d (calls: %d)',[res,numoperations],etInfo);
  229. cout('Press <ENTER> to Exit',ccYellow);
  230. ConsoleWaitForEnterKey;
  231. iocContainer.Free;
  232. except
  233. on E: Exception do
  234. Writeln(E.ClassName, ': ', E.Message);
  235. end;
  236. end.