/mcs/class/referencesource/System.WorkflowServices/System/ServiceModel/Dispatcher/ServiceOperationInvoker.cs

https://github.com/pruiz/mono · C# · 334 lines · 275 code · 51 blank · 8 comment · 31 complexity · 149dc7735ac4a095a31555ad6e8a4809 MD5 · raw file

  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Dispatcher
  5. {
  6. using System;
  7. using System.Diagnostics.CodeAnalysis;
  8. using System.Runtime;
  9. using System.ServiceModel.Description;
  10. using System.ServiceModel.Diagnostics;
  11. class ServiceOperationInvoker : IOperationInvoker
  12. {
  13. bool canCreateInstance;
  14. bool completesInstance;
  15. bool contractCausesSave;
  16. IOperationInvoker innerInvoker;
  17. public ServiceOperationInvoker(IOperationInvoker innerInvoker, bool completesInstance, bool canCreateInstance, bool contractCausesSave)
  18. {
  19. if (innerInvoker == null)
  20. {
  21. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("innerInvoker");
  22. }
  23. this.innerInvoker = innerInvoker;
  24. this.completesInstance = completesInstance;
  25. this.canCreateInstance = canCreateInstance;
  26. this.contractCausesSave = contractCausesSave;
  27. }
  28. public bool IsSynchronous
  29. {
  30. get { return this.innerInvoker.IsSynchronous; }
  31. }
  32. public object[] AllocateInputs()
  33. {
  34. return this.innerInvoker.AllocateInputs();
  35. }
  36. public object Invoke(object instance, object[] inputs, out object[] outputs)
  37. {
  38. if (instance == null)
  39. {
  40. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("instance");
  41. }
  42. ServiceDurableInstance durableInstance = instance as ServiceDurableInstance;
  43. if (durableInstance == null)
  44. {
  45. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  46. new InvalidOperationException(
  47. SR2.GetString(SR2.InvokeCalledWithWrongType, typeof(DurableServiceAttribute).Name)));
  48. }
  49. object serviceInstance = durableInstance.StartOperation(this.canCreateInstance);
  50. Exception operationException = null;
  51. bool failFast = false;
  52. try
  53. {
  54. return this.innerInvoker.Invoke(serviceInstance, inputs, out outputs);
  55. }
  56. catch (Exception e)
  57. {
  58. if (Fx.IsFatal(e))
  59. {
  60. failFast = true;
  61. throw;
  62. }
  63. operationException = e;
  64. ServiceErrorHandler.MarkException(e);
  65. throw;
  66. }
  67. finally
  68. {
  69. if (!failFast)
  70. {
  71. durableInstance.FinishOperation(this.completesInstance, this.contractCausesSave, operationException);
  72. }
  73. }
  74. }
  75. public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
  76. {
  77. if (instance == null)
  78. {
  79. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("instance");
  80. }
  81. ServiceDurableInstance durableInstance = instance as ServiceDurableInstance;
  82. if (durableInstance == null)
  83. {
  84. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  85. new InvalidOperationException(
  86. SR2.GetString(SR2.InvokeCalledWithWrongType, typeof(DurableServiceAttribute).Name)));
  87. }
  88. return new InvokeAsyncResult(durableInstance, inputs, this, this.canCreateInstance, callback, state);
  89. }
  90. public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
  91. {
  92. return InvokeAsyncResult.End(out outputs, result);
  93. }
  94. public class InvokeAsyncResult : AsyncResult
  95. {
  96. static AsyncCallback finishCallback = Fx.ThunkCallback(new AsyncCallback(FinishComplete));
  97. static AsyncCallback invokeCallback = Fx.ThunkCallback(new AsyncCallback(InvokeComplete));
  98. static AsyncCallback startCallback = Fx.ThunkCallback(new AsyncCallback(StartComplete));
  99. Exception completionException;
  100. ServiceDurableInstance durableInstance;
  101. object[] inputs;
  102. ServiceOperationInvoker invoker;
  103. OperationContext operationContext;
  104. object[] outputs;
  105. object returnValue;
  106. object serviceInstance;
  107. public InvokeAsyncResult(ServiceDurableInstance instance, object[] inputs, ServiceOperationInvoker invoker, bool canCreateInstance, AsyncCallback callback, object state)
  108. : base(callback, state)
  109. {
  110. this.invoker = invoker;
  111. this.inputs = inputs;
  112. this.durableInstance = instance;
  113. this.operationContext = OperationContext.Current;
  114. IAsyncResult result = this.durableInstance.BeginStartOperation(canCreateInstance, startCallback, this);
  115. if (result.CompletedSynchronously)
  116. {
  117. this.serviceInstance = this.durableInstance.EndStartOperation(result);
  118. if (DoInvoke())
  119. {
  120. Complete(true, this.completionException);
  121. }
  122. }
  123. }
  124. public static object End(out object[] outputs, IAsyncResult result)
  125. {
  126. InvokeAsyncResult invokeResult = AsyncResult.End<InvokeAsyncResult>(result);
  127. outputs = invokeResult.outputs;
  128. return invokeResult.returnValue;
  129. }
  130. // We pass the exception to another thread
  131. [SuppressMessage("Reliability", "Reliability104")]
  132. [SuppressMessage("Microsoft.Design", "CA1031")]
  133. static void FinishComplete(IAsyncResult result)
  134. {
  135. if (result.CompletedSynchronously)
  136. {
  137. return;
  138. }
  139. InvokeAsyncResult invokeResult = result.AsyncState as InvokeAsyncResult;
  140. Fx.Assert(invokeResult != null, "Async state should have been of type InvokeAsyncResult.");
  141. try
  142. {
  143. invokeResult.durableInstance.EndFinishOperation(result);
  144. }
  145. catch (Exception e)
  146. {
  147. if (Fx.IsFatal(e))
  148. {
  149. throw;
  150. }
  151. invokeResult.completionException = e;
  152. }
  153. invokeResult.Complete(false, invokeResult.completionException);
  154. }
  155. // We pass the exception to another thread
  156. [SuppressMessage("Reliability", "Reliability104")]
  157. [SuppressMessage("Microsoft.Design", "CA1031")]
  158. static void InvokeComplete(IAsyncResult resultParameter)
  159. {
  160. if (resultParameter.CompletedSynchronously)
  161. {
  162. return;
  163. }
  164. InvokeAsyncResult invokeResult = resultParameter.AsyncState as InvokeAsyncResult;
  165. Fx.Assert(invokeResult != null,
  166. "Async state should have been of type InvokeAsyncResult.");
  167. try
  168. {
  169. invokeResult.returnValue = invokeResult.invoker.innerInvoker.InvokeEnd(invokeResult.serviceInstance, out invokeResult.outputs, resultParameter);
  170. }
  171. catch (Exception e)
  172. {
  173. if (Fx.IsFatal(e))
  174. {
  175. throw;
  176. }
  177. ServiceErrorHandler.MarkException(e);
  178. invokeResult.completionException = e;
  179. }
  180. finally
  181. {
  182. if (invokeResult.DoFinish())
  183. {
  184. invokeResult.Complete(false, invokeResult.completionException);
  185. }
  186. }
  187. }
  188. // We pass the exception to another thread
  189. [SuppressMessage("Reliability", "Reliability104")]
  190. [SuppressMessage("Microsoft.Design", "CA1031")]
  191. static void StartComplete(IAsyncResult resultParameter)
  192. {
  193. if (resultParameter.CompletedSynchronously)
  194. {
  195. return;
  196. }
  197. InvokeAsyncResult invokeResult = resultParameter.AsyncState as InvokeAsyncResult;
  198. Fx.Assert(invokeResult != null,
  199. "Async state should have been of type InvokeAsyncResult.");
  200. try
  201. {
  202. invokeResult.serviceInstance = invokeResult.durableInstance.EndStartOperation(resultParameter);
  203. }
  204. catch (Exception e)
  205. {
  206. if (Fx.IsFatal(e))
  207. {
  208. throw;
  209. }
  210. invokeResult.Complete(false, e);
  211. return;
  212. }
  213. if (invokeResult.DoInvoke())
  214. {
  215. invokeResult.Complete(false, invokeResult.completionException);
  216. }
  217. }
  218. // We pass the exception to another thread
  219. [SuppressMessage("Reliability", "Reliability104")]
  220. [SuppressMessage("Microsoft.Design", "CA1031")]
  221. bool DoFinish()
  222. {
  223. try
  224. {
  225. IAsyncResult result = this.durableInstance.BeginFinishOperation(this.invoker.completesInstance, this.invoker.contractCausesSave, this.completionException, finishCallback, this);
  226. if (result.CompletedSynchronously)
  227. {
  228. this.durableInstance.EndFinishOperation(result);
  229. return true;
  230. }
  231. }
  232. catch (Exception e)
  233. {
  234. if (Fx.IsFatal(e))
  235. {
  236. throw;
  237. }
  238. this.completionException = e;
  239. return true;
  240. }
  241. return false;
  242. }
  243. // We pass the exception to another thread
  244. [SuppressMessage("Reliability", "Reliability104")]
  245. [SuppressMessage("Microsoft.Design", "CA1031")]
  246. bool DoInvoke()
  247. {
  248. bool finishNow = false;
  249. try
  250. {
  251. IAsyncResult result = null;
  252. using (OperationContextScope operationScope = new OperationContextScope(this.operationContext))
  253. {
  254. result = this.invoker.innerInvoker.InvokeBegin(this.serviceInstance, this.inputs, invokeCallback, this);
  255. }
  256. if (result.CompletedSynchronously)
  257. {
  258. this.returnValue = this.invoker.innerInvoker.InvokeEnd(this.serviceInstance, out this.outputs, result);
  259. finishNow = true;
  260. }
  261. }
  262. catch (Exception e)
  263. {
  264. if (Fx.IsFatal(e))
  265. {
  266. throw;
  267. }
  268. ServiceErrorHandler.MarkException(e);
  269. this.completionException = e;
  270. finishNow = true;
  271. }
  272. if (finishNow)
  273. {
  274. if (DoFinish())
  275. {
  276. return true;
  277. }
  278. }
  279. return false;
  280. }
  281. }
  282. }
  283. }