PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Castle.Facilities.Synchronize/Result.Void.cs

https://github.com/HEskandari/Castle.InversionOfControl
C# | 439 lines | 206 code | 43 blank | 190 comment | 17 complexity | 74bc1426a2064c145d7092f12ce0e697 MD5 | raw file
  1. // Copyright 2004-2009 Castle Project - http://www.castleproject.org/
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. namespace Castle.Facilities.Synchronize
  15. {
  16. using System;
  17. /// <summary>
  18. /// Delegate called when results are available.
  19. /// </summary>
  20. /// <param name="result">The result.</param>
  21. public delegate void ResultDelegate(Result result);
  22. /// <summary>
  23. /// Delegate called when typed results are available.
  24. /// </summary>
  25. /// <typeparam name="T">The result type.</typeparam>
  26. /// <param name="result">The result.</param>
  27. public delegate void ResultDelegate<T>(Result<T> result);
  28. /// <summary>
  29. /// Represents the result of an asynchronous operation.
  30. /// </summary>
  31. public class Result : AbstractAsyncResult
  32. {
  33. private object guard = new object();
  34. private AsyncCallback asyncCallback;
  35. [ThreadStatic] internal static Result Last = null;
  36. /// <summary>
  37. /// Initializes the <see cref="Result"/>.
  38. /// </summary>
  39. internal Result()
  40. : base(CallCallback, null)
  41. {
  42. }
  43. /// <summary>
  44. /// Gets the output values.
  45. /// </summary>
  46. public object[] OutValues { get; private set; }
  47. /// <summary>
  48. /// Gets the unbound output values.
  49. /// </summary>
  50. public object[] UnboundOutValues { get; private set; }
  51. /// <summary>
  52. /// Waits for the result to complete.
  53. /// </summary>
  54. public void End()
  55. {
  56. Result.End(this);
  57. }
  58. /// <summary>
  59. /// Waits for the result to complete with output.
  60. /// </summary>
  61. /// <typeparam name="TOut1">The output type.</typeparam>
  62. /// <param name="out1">The output value.</param>
  63. public void End<TOut1>(out TOut1 out1)
  64. {
  65. End();
  66. out1 = (TOut1)ExtractOutOfType(typeof(TOut1), 0);
  67. CreateUnboundOutValues(1);
  68. }
  69. /// <summary>
  70. /// Waits for the result to complete with outputs.
  71. /// </summary>
  72. /// <typeparam name="TOut1">The output type.</typeparam>
  73. /// <param name="result">The asynchronous result.</param>
  74. /// <param name="out1">The output value.</param>
  75. public static void End<TOut1>(IAsyncResult result, out TOut1 out1)
  76. {
  77. EnsureResult(result).End(out out1);
  78. }
  79. /// <summary>
  80. /// Waits for the result to complete with outputs.
  81. /// </summary>
  82. /// <typeparam name="TOut1">The first output type.</typeparam>
  83. /// <typeparam name="TOut2">The first output type.</typeparam>
  84. /// <param name="out1">The first output type.</param>
  85. /// <param name="out2">The second output value.</param>
  86. public void End<TOut1, TOut2>(out TOut1 out1, out TOut2 out2)
  87. {
  88. End();
  89. out1 = (TOut1)ExtractOutOfType(typeof(TOut1), 0);
  90. out2 = (TOut2)ExtractOutOfType(typeof(TOut2), 1);
  91. CreateUnboundOutValues(2);
  92. }
  93. /// <summary>
  94. /// Waits for the result to complete with outputs.
  95. /// </summary>
  96. /// <typeparam name="TOut1">The first output type.</typeparam>
  97. /// <typeparam name="TOut2">The first output type.</typeparam>
  98. /// <param name="result">The asynchronous result.</param>
  99. /// <param name="out1">The first output type.</param>
  100. /// <param name="out2">The second output value.</param>
  101. public static void End<TOut1, TOut2>(IAsyncResult result, out TOut1 out1, out TOut2 out2)
  102. {
  103. EnsureResult(result).End(out out1, out out2);
  104. }
  105. /// <summary>
  106. /// Waits for the result to complete with outputs.
  107. /// </summary>
  108. /// <typeparam name="TOut1">The first output type.</typeparam>
  109. /// <typeparam name="TOut2">The second output type.</typeparam>
  110. /// <typeparam name="TOut3">The third output type.</typeparam>
  111. /// <param name="out1">The first output type.</param>
  112. /// <param name="out2">The second output type.</param>
  113. /// <param name="out3">The third output type.</param>
  114. public void End<TOut1, TOut2, TOut3>(out TOut1 out1, out TOut2 out2, out TOut3 out3)
  115. {
  116. End();
  117. out1 = (TOut1)ExtractOutOfType(typeof(TOut1), 0);
  118. out2 = (TOut2)ExtractOutOfType(typeof(TOut2), 1);
  119. out3 = (TOut3)ExtractOutOfType(typeof(TOut3), 2);
  120. CreateUnboundOutValues(3);
  121. }
  122. /// <summary>
  123. /// Waits for the result to complete with outputs.
  124. /// </summary>
  125. /// <typeparam name="TOut1">The first output type.</typeparam>
  126. /// <typeparam name="TOut2">The second output type.</typeparam>
  127. /// <typeparam name="TOut3">The third output type.</typeparam>
  128. /// <param name="result">The asynchronous result.</param>
  129. /// <param name="out1">The first output type.</param>
  130. /// <param name="out2">The second output type.</param>
  131. /// <param name="out3">The third output type.</param>
  132. public static void End<TOut1, TOut2, TOut3>(IAsyncResult result, out TOut1 out1, out TOut2 out2, out TOut3 out3)
  133. {
  134. EnsureResult(result).End(out out1, out out2, out out3);
  135. }
  136. /// <summary>
  137. /// Waits for the result to complete with outputs.
  138. /// </summary>
  139. /// <typeparam name="TOut1">The first output type.</typeparam>
  140. /// <typeparam name="TOut2">The second output type.</typeparam>
  141. /// <typeparam name="TOut3">The third output type.</typeparam>
  142. /// <typeparam name="TOut4">The fourth output type.</typeparam>
  143. /// <param name="out1">The first output type.</param>
  144. /// <param name="out2">The second output type.</param>
  145. /// <param name="out3">The third output type.</param>
  146. /// <param name="out4">The fourth output value</param>
  147. public void End<TOut1, TOut2, TOut3, TOut4>(out TOut1 out1, out TOut2 out2, out TOut3 out3, out TOut4 out4)
  148. {
  149. End();
  150. out1 = (TOut1)ExtractOutOfType(typeof(TOut1), 0);
  151. out2 = (TOut2)ExtractOutOfType(typeof(TOut2), 1);
  152. out3 = (TOut3)ExtractOutOfType(typeof(TOut3), 2);
  153. out4 = (TOut4)ExtractOutOfType(typeof(TOut4), 3);
  154. CreateUnboundOutValues(4);
  155. }
  156. /// <summary>
  157. /// Waits for the result to complete with outputs.
  158. /// </summary>
  159. /// <typeparam name="TOut1">The first output type.</typeparam>
  160. /// <typeparam name="TOut2">The second output type.</typeparam>
  161. /// <typeparam name="TOut3">The third output type.</typeparam>
  162. /// <typeparam name="TOut4">The fourth output type.</typeparam>
  163. /// <param name="result">The asynchronous result.</param>
  164. /// <param name="out1">The first output type.</param>
  165. /// <param name="out2">The second output type.</param>
  166. /// <param name="out3">The third output type.</param>
  167. /// <param name="out4">The fourth output value</param>
  168. public void End<TOut1, TOut2, TOut3, TOut4>(IAsyncResult result, out TOut1 out1, out TOut2 out2,
  169. out TOut3 out3, out TOut4 out4)
  170. {
  171. EnsureResult(result).End(out out1, out out2, out out3, out out4);
  172. }
  173. /// <summary>
  174. /// Gets the output argument at index <paramref name="index"/>.
  175. /// </summary>
  176. /// <typeparam name="TOut">The output type..</typeparam>
  177. /// <param name="index">The output index.</param>
  178. /// <returns>The output value.</returns>
  179. public TOut GetOutArg<TOut>(int index)
  180. {
  181. return (TOut)ExtractOutOfType(typeof(TOut), index);
  182. }
  183. /// <summary>
  184. /// Gets the unbound output argument at index <paramref name="index"/>.
  185. /// </summary>
  186. /// <typeparam name="TOut">The output type.</typeparam>
  187. /// <param name="index">The output index.</param>
  188. /// <returns>The output value.</returns>
  189. public TOut GetUnboundOutArg<TOut>(int index)
  190. {
  191. return (TOut)ExtractUnboundOutOfType(typeof(TOut), index);
  192. }
  193. /// <summary>
  194. /// Gets the result of the last called made.
  195. /// </summary>
  196. /// <param name="action">The action to execute.</param>
  197. /// <returns>The result handle.</returns>
  198. public static Result Of(Action action)
  199. {
  200. action();
  201. return ResetLastResult();
  202. }
  203. /// <summary>
  204. /// Gets the result of the last called made.
  205. /// </summary>
  206. /// <param name="action">The action to execute.</param>
  207. /// <param name="callback">The callback.</param>
  208. /// <param name="state">The async state.</param>
  209. /// <returns>The result handle.</returns>
  210. public static Result Of(Action action, AsyncCallback callback, object state)
  211. {
  212. var result = Result.Of(action);
  213. result.SetCallbackInfo(callback, state);
  214. return result;
  215. }
  216. /// <summary>
  217. /// Gets the result of the last called made.
  218. /// </summary>
  219. /// <param name="action">The action to execute.</param>
  220. /// <param name="callback">The callback.</param>
  221. /// <param name="state">The async state.</param>
  222. /// <returns>The result handle.</returns>
  223. public static Result Of(Action action, ResultDelegate callback, object state)
  224. {
  225. var result = Result.Of(action);
  226. result.SetCallbackInfo((IAsyncResult cb) => callback(result), state);
  227. return result;
  228. }
  229. /// <summary>
  230. /// Gets the result of the last called made.
  231. /// </summary>
  232. /// <typeparam name="T">The result type.</typeparam>
  233. /// <param name="ignored"></param>
  234. /// <returns>The result handle.</returns>
  235. public static Result<T> Of<T>(T ignored)
  236. {
  237. return new Result<T>(ResetLastResult());
  238. }
  239. /// <summary>
  240. /// Gets the result of the last called made.
  241. /// </summary>
  242. /// <typeparam name="T">The result type.</typeparam>
  243. /// <param name="ignored"></param>
  244. /// <param name="callback">The callback.</param>
  245. /// <param name="state">The async state.</param>
  246. /// <returns>The result handle.</returns>
  247. public static Result<T> Of<T>(T ignored, AsyncCallback callback, object state)
  248. {
  249. var result = Result.Of(ignored);
  250. result.SetCallbackInfo(callback, state);
  251. return result;
  252. }
  253. /// <summary>
  254. /// Gets the result of the last called made.
  255. /// </summary>
  256. /// <typeparam name="T">The result type.</typeparam>
  257. /// <param name="ignored"></param>
  258. /// <param name="callback">The callback.</param>
  259. /// <param name="state">The async state.</param>
  260. /// <returns>The result handle.</returns>
  261. public static Result<T> Of<T>(T ignored, ResultDelegate<T> callback, object state)
  262. {
  263. var result = Result.Of(ignored);
  264. result.SetCallbackInfo((IAsyncResult cb) => callback(result), state);
  265. return result;
  266. }
  267. /// <summary>
  268. /// Completes the asynchronous request.
  269. /// </summary>
  270. /// <param name="synchronously">true if synchronously.</param>
  271. /// <param name="result">The result.</param>
  272. /// <param name="outs">The additional outputs.</param>
  273. internal void SetValues(bool synchronously, object result, object[] outs)
  274. {
  275. lock (guard)
  276. {
  277. OutValues = outs;
  278. Complete(synchronously, result);
  279. }
  280. }
  281. /// <summary>
  282. /// Completes the asynchronous request with exception.
  283. /// </summary>
  284. /// <param name="synchronously">true if synchronously.</param>
  285. /// <param name="exception">The exception.</param>
  286. internal void SetException(bool synchronously, Exception exception)
  287. {
  288. lock (guard)
  289. {
  290. Complete(synchronously, exception);
  291. }
  292. }
  293. /// <summary>
  294. /// Set the asynchronous callback information.
  295. /// </summary>
  296. /// <param name="callback">The callback.</param>
  297. /// <param name="state">The async state.</param>
  298. internal void SetCallbackInfo(AsyncCallback callback, object state)
  299. {
  300. if (callback != null) lock (guard)
  301. {
  302. AsyncState = state;
  303. asyncCallback = callback;
  304. if (IsCompleted)
  305. {
  306. asyncCallback(this);
  307. }
  308. }
  309. }
  310. private static void CallCallback(IAsyncResult asyncResult)
  311. {
  312. var result = (Result)asyncResult;
  313. if (result.asyncCallback != null)
  314. {
  315. result.asyncCallback(asyncResult);
  316. }
  317. }
  318. private static Result ResetLastResult()
  319. {
  320. var last = Result.Last;
  321. if (last == null)
  322. {
  323. throw new InvalidOperationException(
  324. "The result is only available for synchronized methods.");
  325. }
  326. Result.Last = null;
  327. return last;
  328. }
  329. /// <summary>
  330. /// Extracts the output at index <paramref name="index"/>
  331. /// </summary>
  332. /// <param name="type">The expected type.</param>
  333. /// <param name="index">The output index.</param>
  334. /// <returns>The extracted output.</returns>
  335. protected internal object ExtractOutOfType(Type type, int index)
  336. {
  337. return ExtractOutOfType(type, index, OutValues);
  338. }
  339. /// <summary>
  340. /// Extracts the unbound output at index <paramref name="index"/>
  341. /// </summary>
  342. /// <param name="type">The expected type.</param>
  343. /// <param name="index">The output index.</param>
  344. /// <returns>The extracted outout.</returns>
  345. protected internal object ExtractUnboundOutOfType(Type type, int index)
  346. {
  347. return ExtractOutOfType(type, index, UnboundOutValues);
  348. }
  349. private object ExtractOutOfType(Type type, int index, object[] outs)
  350. {
  351. if (outs == null)
  352. {
  353. throw new InvalidOperationException("Out arguments are not available. Did you forget to call End?");
  354. }
  355. if (index >= outs.Length)
  356. {
  357. throw new IndexOutOfRangeException(string.Format(
  358. "There is no out argument at index {0}. Please check the method signature.", index));
  359. }
  360. object outArg = outs[index];
  361. if (outArg == null && type.IsValueType)
  362. {
  363. throw new InvalidOperationException(string.Format(
  364. "The out argument at index {0} is a value type and cannot be null. Please check the method signature.", index));
  365. }
  366. if (!type.IsInstanceOfType(outArg))
  367. {
  368. throw new InvalidOperationException(string.Format(
  369. "There is a type mismatch for the out argument at index {0}. Expected {1}, but found {2}. Please check the method signature.",
  370. index, type.FullName, outArg.GetType().FullName));
  371. }
  372. return outArg;
  373. }
  374. /// <summary>
  375. /// Creates the unbound output values starting at <paramref name="fromIndex"/>.
  376. /// </summary>
  377. /// <param name="fromIndex">The starting index.</param>
  378. protected internal void CreateUnboundOutValues(int fromIndex)
  379. {
  380. UnboundOutValues = new object[Math.Max(0, OutValues.Length - fromIndex)];
  381. if (UnboundOutValues.Length > 0)
  382. {
  383. Array.Copy(OutValues, fromIndex, UnboundOutValues, 0, UnboundOutValues.Length);
  384. }
  385. }
  386. internal static Result EnsureResult(IAsyncResult asyncResult)
  387. {
  388. var result = asyncResult as Result;
  389. if (result == null)
  390. {
  391. throw new InvalidOperationException("Unrecoginized IAsyncResult, was this from a call to Result.Of()?");
  392. }
  393. return result;
  394. }
  395. }
  396. }