OperationDescription.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Description
  5. {
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.ComponentModel;
  9. using System.Diagnostics;
  10. using System.Net.Security;
  11. using System.Reflection;
  12. using System.ServiceModel.Security;
  13. [DebuggerDisplay("Name={name}, IsInitiating={isInitiating}, IsTerminating={isTerminating}")]
  14. public class OperationDescription
  15. {
  16. internal const string SessionOpenedAction = Channels.WebSocketTransportSettings.ConnectionOpenedAction;
  17. XmlName name;
  18. bool isInitiating;
  19. bool isTerminating;
  20. bool isSessionOpenNotificationEnabled;
  21. ContractDescription declaringContract;
  22. FaultDescriptionCollection faults;
  23. MessageDescriptionCollection messages;
  24. KeyedByTypeCollection<IOperationBehavior> behaviors;
  25. Collection<Type> knownTypes;
  26. MethodInfo beginMethod;
  27. MethodInfo endMethod;
  28. MethodInfo syncMethod;
  29. MethodInfo taskMethod;
  30. ProtectionLevel protectionLevel;
  31. bool hasProtectionLevel;
  32. bool validateRpcWrapperName = true;
  33. bool hasNoDisposableParameters;
  34. public OperationDescription(string name, ContractDescription declaringContract)
  35. {
  36. if (name == null)
  37. {
  38. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("name");
  39. }
  40. if (name.Length == 0)
  41. {
  42. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  43. new ArgumentOutOfRangeException("name", SR.GetString(SR.SFxOperationDescriptionNameCannotBeEmpty)));
  44. }
  45. this.name = new XmlName(name, true /*isEncoded*/);
  46. if (declaringContract == null)
  47. {
  48. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("declaringContract");
  49. }
  50. this.declaringContract = declaringContract;
  51. this.isInitiating = true;
  52. this.isTerminating = false;
  53. this.faults = new FaultDescriptionCollection();
  54. this.messages = new MessageDescriptionCollection();
  55. this.behaviors = new KeyedByTypeCollection<IOperationBehavior>();
  56. this.knownTypes = new Collection<Type>();
  57. }
  58. internal OperationDescription(string name, ContractDescription declaringContract, bool validateRpcWrapperName)
  59. : this(name, declaringContract)
  60. {
  61. this.validateRpcWrapperName = validateRpcWrapperName;
  62. }
  63. public KeyedCollection<Type, IOperationBehavior> OperationBehaviors
  64. {
  65. get { return this.Behaviors; }
  66. }
  67. [EditorBrowsable(EditorBrowsableState.Never)]
  68. public KeyedByTypeCollection<IOperationBehavior> Behaviors
  69. {
  70. get { return behaviors; }
  71. }
  72. // Not serializable on purpose, metadata import/export cannot
  73. // produce it, only available when binding to runtime
  74. public MethodInfo TaskMethod
  75. {
  76. get { return this.taskMethod; }
  77. set { this.taskMethod = value; }
  78. }
  79. // Not serializable on purpose, metadata import/export cannot
  80. // produce it, only available when binding to runtime
  81. public MethodInfo SyncMethod
  82. {
  83. get { return this.syncMethod; }
  84. set { this.syncMethod = value; }
  85. }
  86. // Not serializable on purpose, metadata import/export cannot
  87. // produce it, only available when binding to runtime
  88. public MethodInfo BeginMethod
  89. {
  90. get { return this.beginMethod; }
  91. set { this.beginMethod = value; }
  92. }
  93. internal MethodInfo OperationMethod
  94. {
  95. get
  96. {
  97. if (this.SyncMethod == null)
  98. {
  99. return this.TaskMethod ?? this.BeginMethod;
  100. }
  101. else
  102. {
  103. return this.SyncMethod;
  104. }
  105. }
  106. }
  107. public ProtectionLevel ProtectionLevel
  108. {
  109. get { return this.protectionLevel; }
  110. set
  111. {
  112. if (!ProtectionLevelHelper.IsDefined(value))
  113. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
  114. this.protectionLevel = value;
  115. this.hasProtectionLevel = true;
  116. }
  117. }
  118. public bool ShouldSerializeProtectionLevel()
  119. {
  120. return this.HasProtectionLevel;
  121. }
  122. public bool HasProtectionLevel
  123. {
  124. get { return this.hasProtectionLevel; }
  125. }
  126. internal bool HasNoDisposableParameters
  127. {
  128. get { return this.hasNoDisposableParameters; }
  129. set { this.hasNoDisposableParameters = value; }
  130. }
  131. // Not serializable on purpose, metadata import/export cannot
  132. // produce it, only available when binding to runtime
  133. public MethodInfo EndMethod
  134. {
  135. get { return this.endMethod; }
  136. set { this.endMethod = value; }
  137. }
  138. public ContractDescription DeclaringContract
  139. {
  140. get { return this.declaringContract; }
  141. set
  142. {
  143. if (value == null)
  144. {
  145. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("DeclaringContract");
  146. }
  147. else
  148. {
  149. this.declaringContract = value;
  150. }
  151. }
  152. }
  153. public FaultDescriptionCollection Faults
  154. {
  155. get { return faults; }
  156. }
  157. public bool IsOneWay
  158. {
  159. get { return this.Messages.Count == 1; }
  160. }
  161. [DefaultValue(false)]
  162. public bool IsInitiating
  163. {
  164. get { return this.isInitiating; }
  165. set { this.isInitiating = value; }
  166. }
  167. internal bool IsServerInitiated()
  168. {
  169. EnsureInvariants();
  170. return Messages[0].Direction == MessageDirection.Output;
  171. }
  172. [DefaultValue(false)]
  173. public bool IsTerminating
  174. {
  175. get { return this.isTerminating; }
  176. set { this.isTerminating = value; }
  177. }
  178. public Collection<Type> KnownTypes
  179. {
  180. get { return this.knownTypes; }
  181. }
  182. // Messages[0] is the 'request' (first of MEP), and for non-oneway MEPs, Messages[1] is the 'response' (second of MEP)
  183. public MessageDescriptionCollection Messages
  184. {
  185. get { return messages; }
  186. }
  187. internal XmlName XmlName
  188. {
  189. get { return name; }
  190. }
  191. internal string CodeName
  192. {
  193. get { return name.DecodedName; }
  194. }
  195. public string Name
  196. {
  197. get { return name.EncodedName; }
  198. }
  199. internal bool IsValidateRpcWrapperName { get { return validateRpcWrapperName; } }
  200. //This property is set during contract inference in a hosted workflow scenario. This is required to handle correct
  201. //transactional invocation from the dispatcher in regards to scenarios involving the TransactedReceiveScope activity
  202. internal bool IsInsideTransactedReceiveScope
  203. {
  204. get;
  205. set;
  206. }
  207. //This property is set during contract inference in a hosted workflow scenario. This is required to handle correct
  208. //transactional invocation from the dispatcher in regards to scenarios involving the TransactedReceiveScope activity
  209. internal bool IsFirstReceiveOfTransactedReceiveScopeTree
  210. {
  211. get;
  212. set;
  213. }
  214. internal Type TaskTResult
  215. {
  216. get;
  217. set;
  218. }
  219. internal bool HasOutputParameters
  220. {
  221. get
  222. {
  223. // For non-oneway operations, Messages[1] is the 'response'
  224. return (this.Messages.Count > 1) &&
  225. (this.Messages[1].Body.Parts.Count > 0);
  226. }
  227. }
  228. internal bool IsSessionOpenNotificationEnabled
  229. {
  230. get { return this.isSessionOpenNotificationEnabled; }
  231. set { this.isSessionOpenNotificationEnabled = value; }
  232. }
  233. internal void EnsureInvariants()
  234. {
  235. if (this.Messages.Count != 1 && this.Messages.Count != 2)
  236. {
  237. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.InvalidOperationException(SR.GetString(SR.SFxOperationMustHaveOneOrTwoMessages, this.Name)));
  238. }
  239. }
  240. internal void ResetProtectionLevel()
  241. {
  242. this.protectionLevel = ProtectionLevel.None;
  243. this.hasProtectionLevel = false;
  244. }
  245. }
  246. }