OperationFormatter.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Dispatcher
  5. {
  6. using System.Collections;
  7. using System.ServiceModel;
  8. using System.ServiceModel.Description;
  9. using System.Collections.Generic;
  10. using System.Collections.ObjectModel;
  11. using System.Diagnostics;
  12. using System.IO;
  13. using System.Runtime.Serialization;
  14. using System.Reflection;
  15. using System.Xml;
  16. using System.ServiceModel.Diagnostics;
  17. using System.ServiceModel.Channels;
  18. using System.Runtime.Diagnostics;
  19. using System.Runtime;
  20. using System.Threading;
  21. abstract class OperationFormatter : IClientMessageFormatter, IDispatchMessageFormatter
  22. {
  23. MessageDescription replyDescription;
  24. MessageDescription requestDescription;
  25. XmlDictionaryString action;
  26. XmlDictionaryString replyAction;
  27. protected StreamFormatter requestStreamFormatter, replyStreamFormatter;
  28. XmlDictionary dictionary;
  29. string operationName;
  30. static object[] emptyObjectArray = new object[0];
  31. public OperationFormatter(OperationDescription description, bool isRpc, bool isEncoded)
  32. {
  33. Validate(description, isRpc, isEncoded);
  34. this.requestDescription = description.Messages[0];
  35. if (description.Messages.Count == 2)
  36. this.replyDescription = description.Messages[1];
  37. int stringCount = 3 + requestDescription.Body.Parts.Count;
  38. if (replyDescription != null)
  39. stringCount += 2 + replyDescription.Body.Parts.Count;
  40. dictionary = new XmlDictionary(stringCount * 2);
  41. GetActions(description, dictionary, out this.action, out this.replyAction);
  42. operationName = description.Name;
  43. requestStreamFormatter = StreamFormatter.Create(requestDescription, operationName, true/*isRequest*/);
  44. if (replyDescription != null)
  45. replyStreamFormatter = StreamFormatter.Create(replyDescription, operationName, false/*isResponse*/);
  46. }
  47. protected abstract void AddHeadersToMessage(Message message, MessageDescription messageDescription, object[] parameters, bool isRequest);
  48. protected abstract void SerializeBody(XmlDictionaryWriter writer, MessageVersion version, string action, MessageDescription messageDescription, object returnValue, object[] parameters, bool isRequest);
  49. protected abstract void GetHeadersFromMessage(Message message, MessageDescription messageDescription, object[] parameters, bool isRequest);
  50. protected abstract object DeserializeBody(XmlDictionaryReader reader, MessageVersion version, string action, MessageDescription messageDescription, object[] parameters, bool isRequest);
  51. protected virtual void WriteBodyAttributes(XmlDictionaryWriter writer, MessageVersion messageVersion)
  52. {
  53. }
  54. internal string RequestAction
  55. {
  56. get
  57. {
  58. if (action != null)
  59. return action.Value;
  60. return null;
  61. }
  62. }
  63. internal string ReplyAction
  64. {
  65. get
  66. {
  67. if (replyAction != null)
  68. return replyAction.Value;
  69. return null;
  70. }
  71. }
  72. protected XmlDictionary Dictionary
  73. {
  74. get { return dictionary; }
  75. }
  76. protected string OperationName
  77. {
  78. get { return this.operationName; }
  79. }
  80. protected MessageDescription ReplyDescription
  81. {
  82. get { return replyDescription; }
  83. }
  84. protected MessageDescription RequestDescription
  85. {
  86. get { return requestDescription; }
  87. }
  88. protected XmlDictionaryString AddToDictionary(string s)
  89. {
  90. return AddToDictionary(dictionary, s);
  91. }
  92. public object DeserializeReply(Message message, object[] parameters)
  93. {
  94. if (message == null)
  95. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
  96. if (parameters == null)
  97. throw TraceUtility.ThrowHelperError(new ArgumentNullException("parameters"), message);
  98. try
  99. {
  100. object result = null;
  101. if (replyDescription.IsTypedMessage)
  102. {
  103. object typeMessageInstance = CreateTypedMessageInstance(replyDescription.MessageType);
  104. TypedMessageParts typedMessageParts = new TypedMessageParts(typeMessageInstance, replyDescription);
  105. object[] parts = new object[typedMessageParts.Count];
  106. GetPropertiesFromMessage(message, replyDescription, parts);
  107. GetHeadersFromMessage(message, replyDescription, parts, false/*isRequest*/);
  108. DeserializeBodyContents(message, parts, false/*isRequest*/);
  109. // copy values into the actual field/properties
  110. typedMessageParts.SetTypedMessageParts(parts);
  111. result = typeMessageInstance;
  112. }
  113. else
  114. {
  115. GetPropertiesFromMessage(message, replyDescription, parameters);
  116. GetHeadersFromMessage(message, replyDescription, parameters, false/*isRequest*/);
  117. result = DeserializeBodyContents(message, parameters, false/*isRequest*/);
  118. }
  119. return result;
  120. }
  121. catch (XmlException xe)
  122. {
  123. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
  124. SR.GetString(SR.SFxErrorDeserializingReplyBodyMore, this.operationName, xe.Message), xe));
  125. }
  126. catch (FormatException fe)
  127. {
  128. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
  129. SR.GetString(SR.SFxErrorDeserializingReplyBodyMore, this.operationName, fe.Message), fe));
  130. }
  131. catch (SerializationException se)
  132. {
  133. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
  134. SR.GetString(SR.SFxErrorDeserializingReplyBodyMore, this.operationName, se.Message), se));
  135. }
  136. }
  137. private static object CreateTypedMessageInstance(Type messageContractType)
  138. {
  139. BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.NonPublic;
  140. try
  141. {
  142. object typeMessageInstance = Activator.CreateInstance(
  143. messageContractType,
  144. bindingFlags,
  145. null, emptyObjectArray, null);
  146. return typeMessageInstance;
  147. }
  148. catch (MissingMethodException mme)
  149. {
  150. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxMessageContractRequiresDefaultConstructor, messageContractType.FullName), mme));
  151. }
  152. }
  153. public void DeserializeRequest(Message message, object[] parameters)
  154. {
  155. if (message == null)
  156. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
  157. if (parameters == null)
  158. throw TraceUtility.ThrowHelperError(new ArgumentNullException("parameters"), message);
  159. try
  160. {
  161. if (requestDescription.IsTypedMessage)
  162. {
  163. object typeMessageInstance = CreateTypedMessageInstance(requestDescription.MessageType);
  164. TypedMessageParts typedMessageParts = new TypedMessageParts(typeMessageInstance, requestDescription);
  165. object[] parts = new object[typedMessageParts.Count];
  166. GetPropertiesFromMessage(message, requestDescription, parts);
  167. GetHeadersFromMessage(message, requestDescription, parts, true/*isRequest*/);
  168. DeserializeBodyContents(message, parts, true/*isRequest*/);
  169. // copy values into the actual field/properties
  170. typedMessageParts.SetTypedMessageParts(parts);
  171. parameters[0] = typeMessageInstance;
  172. }
  173. else
  174. {
  175. GetPropertiesFromMessage(message, requestDescription, parameters);
  176. GetHeadersFromMessage(message, requestDescription, parameters, true/*isRequest*/);
  177. DeserializeBodyContents(message, parameters, true/*isRequest*/);
  178. }
  179. }
  180. catch (XmlException xe)
  181. {
  182. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  183. OperationFormatter.CreateDeserializationFailedFault(
  184. SR.GetString(SR.SFxErrorDeserializingRequestBodyMore, this.operationName, xe.Message),
  185. xe));
  186. }
  187. catch (FormatException fe)
  188. {
  189. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  190. OperationFormatter.CreateDeserializationFailedFault(
  191. SR.GetString(SR.SFxErrorDeserializingRequestBodyMore, this.operationName, fe.Message),
  192. fe));
  193. }
  194. catch (SerializationException se)
  195. {
  196. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(
  197. SR.GetString(SR.SFxErrorDeserializingRequestBodyMore, this.operationName, se.Message),
  198. se));
  199. }
  200. }
  201. object DeserializeBodyContents(Message message, object[] parameters, bool isRequest)
  202. {
  203. MessageDescription messageDescription;
  204. StreamFormatter streamFormatter;
  205. SetupStreamAndMessageDescription(isRequest, out streamFormatter, out messageDescription);
  206. if (streamFormatter != null)
  207. {
  208. object retVal = null;
  209. streamFormatter.Deserialize(parameters, ref retVal, message);
  210. return retVal;
  211. }
  212. if (message.IsEmpty)
  213. {
  214. return null;
  215. }
  216. else
  217. {
  218. XmlDictionaryReader reader = message.GetReaderAtBodyContents();
  219. using (reader)
  220. {
  221. object body = DeserializeBody(reader, message.Version, RequestAction, messageDescription, parameters, isRequest);
  222. message.ReadFromBodyContentsToEnd(reader);
  223. return body;
  224. }
  225. }
  226. }
  227. public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
  228. {
  229. object[] parts = null;
  230. if (messageVersion == null)
  231. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("messageVersion");
  232. if (parameters == null)
  233. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters");
  234. if (requestDescription.IsTypedMessage)
  235. {
  236. TypedMessageParts typedMessageParts = new TypedMessageParts(parameters[0], requestDescription);
  237. // copy values from the actual field/properties
  238. parts = new object[typedMessageParts.Count];
  239. typedMessageParts.GetTypedMessageParts(parts);
  240. }
  241. else
  242. {
  243. parts = parameters;
  244. }
  245. Message msg = new OperationFormatterMessage(this, messageVersion,
  246. action == null ? null : ActionHeader.Create(action, messageVersion.Addressing),
  247. parts, null, true/*isRequest*/);
  248. AddPropertiesToMessage(msg, requestDescription, parts);
  249. AddHeadersToMessage(msg, requestDescription, parts, true /*isRequest*/);
  250. return msg;
  251. }
  252. public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
  253. {
  254. object[] parts = null;
  255. object resultPart = null;
  256. if (messageVersion == null)
  257. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("messageVersion");
  258. if (parameters == null)
  259. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters");
  260. if (replyDescription.IsTypedMessage)
  261. {
  262. // If the response is a typed message then it must
  263. // me the response (as opposed to an out param). We will
  264. // serialize the response in the exact same way that we
  265. // would serialize a bunch of outs (with no return value).
  266. TypedMessageParts typedMessageParts = new TypedMessageParts(result, replyDescription);
  267. // make a copy of the list so that we have the actual values of the field/properties
  268. parts = new object[typedMessageParts.Count];
  269. typedMessageParts.GetTypedMessageParts(parts);
  270. resultPart = null;
  271. }
  272. else
  273. {
  274. parts = parameters;
  275. resultPart = result;
  276. }
  277. Message msg = new OperationFormatterMessage(this, messageVersion,
  278. replyAction == null ? null : ActionHeader.Create(replyAction, messageVersion.Addressing),
  279. parts, resultPart, false/*isRequest*/);
  280. AddPropertiesToMessage(msg, replyDescription, parts);
  281. AddHeadersToMessage(msg, replyDescription, parts, false /*isRequest*/);
  282. return msg;
  283. }
  284. void SetupStreamAndMessageDescription(bool isRequest, out StreamFormatter streamFormatter, out MessageDescription messageDescription)
  285. {
  286. if (isRequest)
  287. {
  288. streamFormatter = requestStreamFormatter;
  289. messageDescription = requestDescription;
  290. }
  291. else
  292. {
  293. streamFormatter = replyStreamFormatter;
  294. messageDescription = replyDescription;
  295. }
  296. }
  297. void SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, object[] parameters, object returnValue, bool isRequest)
  298. {
  299. MessageDescription messageDescription;
  300. StreamFormatter streamFormatter;
  301. SetupStreamAndMessageDescription(isRequest, out streamFormatter, out messageDescription);
  302. if (streamFormatter != null)
  303. {
  304. streamFormatter.Serialize(writer, parameters, returnValue);
  305. return;
  306. }
  307. SerializeBody(writer, version, RequestAction, messageDescription, returnValue, parameters, isRequest);
  308. }
  309. IAsyncResult BeginSerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, object[] parameters, object returnValue, bool isRequest,
  310. AsyncCallback callback, object state)
  311. {
  312. return new SerializeBodyContentsAsyncResult(this, writer, version, parameters, returnValue, isRequest, callback, state);
  313. }
  314. void EndSerializeBodyContents(IAsyncResult result)
  315. {
  316. SerializeBodyContentsAsyncResult.End(result);
  317. }
  318. class SerializeBodyContentsAsyncResult : AsyncResult
  319. {
  320. static AsyncCompletion handleEndSerializeBodyContents = new AsyncCompletion(HandleEndSerializeBodyContents);
  321. StreamFormatter streamFormatter;
  322. internal SerializeBodyContentsAsyncResult(OperationFormatter operationFormatter, XmlDictionaryWriter writer, MessageVersion version, object[] parameters,
  323. object returnValue, bool isRequest, AsyncCallback callback, object state)
  324. : base(callback, state)
  325. {
  326. bool completeSelf = true;
  327. MessageDescription messageDescription;
  328. StreamFormatter streamFormatter;
  329. operationFormatter.SetupStreamAndMessageDescription(isRequest, out streamFormatter, out messageDescription);
  330. if (streamFormatter != null)
  331. {
  332. this.streamFormatter = streamFormatter;
  333. IAsyncResult result = streamFormatter.BeginSerialize(writer, parameters, returnValue, PrepareAsyncCompletion(handleEndSerializeBodyContents), this);
  334. completeSelf = SyncContinue(result);
  335. }
  336. else
  337. {
  338. operationFormatter.SerializeBody(writer, version, operationFormatter.RequestAction, messageDescription, returnValue, parameters, isRequest);
  339. completeSelf = true;
  340. }
  341. if (completeSelf)
  342. {
  343. Complete(true);
  344. }
  345. }
  346. static bool HandleEndSerializeBodyContents(IAsyncResult result)
  347. {
  348. SerializeBodyContentsAsyncResult thisPtr = (SerializeBodyContentsAsyncResult)result.AsyncState;
  349. thisPtr.streamFormatter.EndSerialize(result);
  350. return true;
  351. }
  352. public static void End(IAsyncResult result)
  353. {
  354. AsyncResult.End<SerializeBodyContentsAsyncResult>(result);
  355. }
  356. }
  357. void AddPropertiesToMessage(Message message, MessageDescription messageDescription, object[] parameters)
  358. {
  359. if (messageDescription.Properties.Count > 0)
  360. {
  361. AddPropertiesToMessageCore(message, messageDescription, parameters);
  362. }
  363. }
  364. void AddPropertiesToMessageCore(Message message, MessageDescription messageDescription, object[] parameters)
  365. {
  366. MessageProperties properties = message.Properties;
  367. MessagePropertyDescriptionCollection propertyDescriptions = messageDescription.Properties;
  368. for (int i = 0; i < propertyDescriptions.Count; i++)
  369. {
  370. MessagePropertyDescription propertyDescription = propertyDescriptions[i];
  371. object parameter = parameters[propertyDescription.Index];
  372. if (null != parameter)
  373. properties.Add(propertyDescription.Name, parameter);
  374. }
  375. }
  376. void GetPropertiesFromMessage(Message message, MessageDescription messageDescription, object[] parameters)
  377. {
  378. if (messageDescription.Properties.Count > 0)
  379. {
  380. GetPropertiesFromMessageCore(message, messageDescription, parameters);
  381. }
  382. }
  383. void GetPropertiesFromMessageCore(Message message, MessageDescription messageDescription, object[] parameters)
  384. {
  385. MessageProperties properties = message.Properties;
  386. MessagePropertyDescriptionCollection propertyDescriptions = messageDescription.Properties;
  387. for (int i = 0; i < propertyDescriptions.Count; i++)
  388. {
  389. MessagePropertyDescription propertyDescription = propertyDescriptions[i];
  390. if (properties.ContainsKey(propertyDescription.Name))
  391. {
  392. parameters[propertyDescription.Index] = properties[propertyDescription.Name];
  393. }
  394. }
  395. }
  396. internal static object GetContentOfMessageHeaderOfT(MessageHeaderDescription headerDescription, object parameterValue, out bool mustUnderstand, out bool relay, out string actor)
  397. {
  398. actor = headerDescription.Actor;
  399. mustUnderstand = headerDescription.MustUnderstand;
  400. relay = headerDescription.Relay;
  401. if (headerDescription.TypedHeader && parameterValue != null)
  402. parameterValue = TypedHeaderManager.GetContent(headerDescription.Type, parameterValue, out mustUnderstand, out relay, out actor);
  403. return parameterValue;
  404. }
  405. internal static bool IsValidReturnValue(MessagePartDescription returnValue)
  406. {
  407. return (returnValue != null) && (returnValue.Type != typeof(void));
  408. }
  409. internal static XmlDictionaryString AddToDictionary(XmlDictionary dictionary, string s)
  410. {
  411. XmlDictionaryString dictionaryString;
  412. if (!dictionary.TryLookup(s, out dictionaryString))
  413. {
  414. dictionaryString = dictionary.Add(s);
  415. }
  416. return dictionaryString;
  417. }
  418. internal static void Validate(OperationDescription operation, bool isRpc, bool isEncoded)
  419. {
  420. if (isEncoded && !isRpc)
  421. {
  422. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxDocEncodedNotSupported, operation.Name)));
  423. }
  424. bool hasVoid = false;
  425. bool hasTypedOrUntypedMessage = false;
  426. bool hasParameter = false;
  427. for (int i = 0; i < operation.Messages.Count; i++)
  428. {
  429. MessageDescription message = operation.Messages[i];
  430. if (message.IsTypedMessage || message.IsUntypedMessage)
  431. {
  432. if (isRpc && operation.IsValidateRpcWrapperName)
  433. {
  434. if (!isEncoded)
  435. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxTypedMessageCannotBeRpcLiteral, operation.Name)));
  436. }
  437. hasTypedOrUntypedMessage = true;
  438. }
  439. else if (message.IsVoid)
  440. hasVoid = true;
  441. else
  442. hasParameter = true;
  443. }
  444. if (hasParameter && hasTypedOrUntypedMessage)
  445. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxTypedOrUntypedMessageCannotBeMixedWithParameters, operation.Name)));
  446. if (isRpc && hasTypedOrUntypedMessage && hasVoid)
  447. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxTypedOrUntypedMessageCannotBeMixedWithVoidInRpc, operation.Name)));
  448. }
  449. internal static void GetActions(OperationDescription description, XmlDictionary dictionary, out XmlDictionaryString action, out XmlDictionaryString replyAction)
  450. {
  451. string actionString, replyActionString;
  452. actionString = description.Messages[0].Action;
  453. if (actionString == MessageHeaders.WildcardAction)
  454. actionString = null;
  455. if (!description.IsOneWay)
  456. replyActionString = description.Messages[1].Action;
  457. else
  458. replyActionString = null;
  459. if (replyActionString == MessageHeaders.WildcardAction)
  460. replyActionString = null;
  461. action = replyAction = null;
  462. if (actionString != null)
  463. action = AddToDictionary(dictionary, actionString);
  464. if (replyActionString != null)
  465. replyAction = AddToDictionary(dictionary, replyActionString);
  466. }
  467. internal static NetDispatcherFaultException CreateDeserializationFailedFault(string reason, Exception innerException)
  468. {
  469. reason = SR.GetString(SR.SFxDeserializationFailed1, reason);
  470. FaultCode code = new FaultCode(FaultCodeConstants.Codes.DeserializationFailed, FaultCodeConstants.Namespaces.NetDispatch);
  471. code = FaultCode.CreateSenderFaultCode(code);
  472. return new NetDispatcherFaultException(reason, code, innerException);
  473. }
  474. internal static void TraceAndSkipElement(XmlReader xmlReader)
  475. {
  476. if (DiagnosticUtility.ShouldTraceVerbose)
  477. {
  478. TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.ElementIgnored, SR.GetString(SR.SFxTraceCodeElementIgnored), new StringTraceRecord("Element", xmlReader.NamespaceURI + ":" + xmlReader.LocalName));
  479. }
  480. xmlReader.Skip();
  481. }
  482. class TypedMessageParts
  483. {
  484. object instance;
  485. MemberInfo[] members;
  486. public TypedMessageParts(object instance, MessageDescription description)
  487. {
  488. if (description == null)
  489. {
  490. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("description"));
  491. }
  492. if (instance == null)
  493. {
  494. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(SR.GetString(SR.SFxTypedMessageCannotBeNull, description.Action)));
  495. }
  496. members = new MemberInfo[description.Body.Parts.Count + description.Properties.Count + description.Headers.Count];
  497. foreach (MessagePartDescription part in description.Headers)
  498. members[part.Index] = part.MemberInfo;
  499. foreach (MessagePartDescription part in description.Properties)
  500. members[part.Index] = part.MemberInfo;
  501. foreach (MessagePartDescription part in description.Body.Parts)
  502. members[part.Index] = part.MemberInfo;
  503. this.instance = instance;
  504. }
  505. object GetValue(int index)
  506. {
  507. MemberInfo memberInfo = members[index];
  508. if (memberInfo.MemberType == MemberTypes.Property)
  509. {
  510. return ((PropertyInfo)members[index]).GetValue(instance, null);
  511. }
  512. else
  513. {
  514. return ((FieldInfo)members[index]).GetValue(instance);
  515. }
  516. }
  517. void SetValue(object value, int index)
  518. {
  519. MemberInfo memberInfo = members[index];
  520. if (memberInfo.MemberType == MemberTypes.Property)
  521. {
  522. ((PropertyInfo)members[index]).SetValue(instance, value, null);
  523. }
  524. else
  525. {
  526. ((FieldInfo)members[index]).SetValue(instance, value);
  527. }
  528. }
  529. internal void GetTypedMessageParts(object[] values)
  530. {
  531. for (int i = 0; i < this.members.Length; i++)
  532. {
  533. values[i] = GetValue(i);
  534. }
  535. }
  536. internal void SetTypedMessageParts(object[] values)
  537. {
  538. for (int i = 0; i < this.members.Length; i++)
  539. {
  540. SetValue(values[i], i);
  541. }
  542. }
  543. internal int Count
  544. {
  545. get { return this.members.Length; }
  546. }
  547. }
  548. internal class OperationFormatterMessage : BodyWriterMessage
  549. {
  550. OperationFormatter operationFormatter;
  551. public OperationFormatterMessage(OperationFormatter operationFormatter, MessageVersion version, ActionHeader action,
  552. object[] parameters, object returnValue, bool isRequest)
  553. : base(version, action, new OperationFormatterBodyWriter(operationFormatter, version, parameters, returnValue, isRequest))
  554. {
  555. this.operationFormatter = operationFormatter;
  556. }
  557. public OperationFormatterMessage(MessageVersion version, string action, BodyWriter bodyWriter) : base(version, action, bodyWriter) { }
  558. OperationFormatterMessage(MessageHeaders headers, KeyValuePair<string, object>[] properties, OperationFormatterBodyWriter bodyWriter)
  559. : base(headers, properties, bodyWriter)
  560. {
  561. operationFormatter = bodyWriter.OperationFormatter;
  562. }
  563. protected override void OnWriteStartBody(XmlDictionaryWriter writer)
  564. {
  565. base.OnWriteStartBody(writer);
  566. operationFormatter.WriteBodyAttributes(writer, this.Version);
  567. }
  568. protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
  569. {
  570. BodyWriter bufferedBodyWriter;
  571. if (BodyWriter.IsBuffered)
  572. {
  573. bufferedBodyWriter = base.BodyWriter;
  574. }
  575. else
  576. {
  577. bufferedBodyWriter = base.BodyWriter.CreateBufferedCopy(maxBufferSize);
  578. }
  579. KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[base.Properties.Count];
  580. ((ICollection<KeyValuePair<string, object>>)base.Properties).CopyTo(properties, 0);
  581. return new OperationFormatterMessageBuffer(base.Headers, properties, bufferedBodyWriter);
  582. }
  583. class OperationFormatterBodyWriter : BodyWriter
  584. {
  585. bool isRequest;
  586. OperationFormatter operationFormatter;
  587. object[] parameters;
  588. object returnValue;
  589. MessageVersion version;
  590. bool onBeginWriteBodyContentsCalled;
  591. public OperationFormatterBodyWriter(OperationFormatter operationFormatter, MessageVersion version,
  592. object[] parameters, object returnValue, bool isRequest)
  593. : base(AreParametersBuffered(isRequest, operationFormatter))
  594. {
  595. this.parameters = parameters;
  596. this.returnValue = returnValue;
  597. this.isRequest = isRequest;
  598. this.operationFormatter = operationFormatter;
  599. this.version = version;
  600. }
  601. object ThisLock
  602. {
  603. get { return this; }
  604. }
  605. static bool AreParametersBuffered(bool isRequest, OperationFormatter operationFormatter)
  606. {
  607. StreamFormatter streamFormatter = isRequest ? operationFormatter.requestStreamFormatter : operationFormatter.replyStreamFormatter;
  608. return streamFormatter == null;
  609. }
  610. protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
  611. {
  612. lock (ThisLock)
  613. {
  614. this.operationFormatter.SerializeBodyContents(writer, this.version, this.parameters, this.returnValue, this.isRequest);
  615. }
  616. }
  617. protected override IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
  618. {
  619. Fx.Assert(!onBeginWriteBodyContentsCalled, "OnBeginWriteBodyContents has already been called");
  620. this.onBeginWriteBodyContentsCalled = true;
  621. return new OnWriteBodyContentsAsyncResult(this, writer, callback, state);
  622. }
  623. protected override void OnEndWriteBodyContents(IAsyncResult result)
  624. {
  625. OnWriteBodyContentsAsyncResult.End(result);
  626. }
  627. internal OperationFormatter OperationFormatter
  628. {
  629. get { return operationFormatter; }
  630. }
  631. class OnWriteBodyContentsAsyncResult : AsyncResult
  632. {
  633. static AsyncCompletion handleEndOnWriteBodyContents = new AsyncCompletion(HandleEndOnWriteBodyContents);
  634. OperationFormatter operationFormatter;
  635. internal OnWriteBodyContentsAsyncResult(OperationFormatterBodyWriter operationFormatterBodyWriter, XmlDictionaryWriter writer, AsyncCallback callback, object state)
  636. : base(callback, state)
  637. {
  638. bool completeSelf = true;
  639. this.operationFormatter = operationFormatterBodyWriter.OperationFormatter;
  640. IAsyncResult result = this.operationFormatter.BeginSerializeBodyContents(writer, operationFormatterBodyWriter.version,
  641. operationFormatterBodyWriter.parameters, operationFormatterBodyWriter.returnValue, operationFormatterBodyWriter.isRequest,
  642. PrepareAsyncCompletion(handleEndOnWriteBodyContents), this);
  643. completeSelf = SyncContinue(result);
  644. if (completeSelf)
  645. {
  646. Complete(true);
  647. }
  648. }
  649. static bool HandleEndOnWriteBodyContents(IAsyncResult result)
  650. {
  651. OnWriteBodyContentsAsyncResult thisPtr = (OnWriteBodyContentsAsyncResult)result.AsyncState;
  652. thisPtr.operationFormatter.EndSerializeBodyContents(result);
  653. return true;
  654. }
  655. public static void End(IAsyncResult result)
  656. {
  657. AsyncResult.End<OnWriteBodyContentsAsyncResult>(result);
  658. }
  659. }
  660. }
  661. class OperationFormatterMessageBuffer : BodyWriterMessageBuffer
  662. {
  663. public OperationFormatterMessageBuffer(MessageHeaders headers,
  664. KeyValuePair<string, object>[] properties, BodyWriter bodyWriter)
  665. : base(headers, properties, bodyWriter)
  666. {
  667. }
  668. public override Message CreateMessage()
  669. {
  670. OperationFormatterBodyWriter operationFormatterBodyWriter = base.BodyWriter as OperationFormatterBodyWriter;
  671. if (operationFormatterBodyWriter == null)
  672. return base.CreateMessage();
  673. lock (ThisLock)
  674. {
  675. if (base.Closed)
  676. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
  677. return new OperationFormatterMessage(base.Headers, base.Properties, operationFormatterBodyWriter);
  678. }
  679. }
  680. }
  681. }
  682. internal abstract class OperationFormatterHeader : MessageHeader
  683. {
  684. protected MessageHeader innerHeader; //use innerHeader to handle versionSupported, actor/role handling etc.
  685. protected OperationFormatter operationFormatter;
  686. protected MessageVersion version;
  687. public OperationFormatterHeader(OperationFormatter operationFormatter, MessageVersion version, string name, string ns, bool mustUnderstand, string actor, bool relay)
  688. {
  689. this.operationFormatter = operationFormatter;
  690. this.version = version;
  691. if (actor != null)
  692. innerHeader = MessageHeader.CreateHeader(name, ns, null/*headerValue*/, mustUnderstand, actor, relay);
  693. else
  694. innerHeader = MessageHeader.CreateHeader(name, ns, null/*headerValue*/, mustUnderstand, "", relay);
  695. }
  696. public override bool IsMessageVersionSupported(MessageVersion messageVersion)
  697. {
  698. return innerHeader.IsMessageVersionSupported(messageVersion);
  699. }
  700. public override string Name
  701. {
  702. get { return innerHeader.Name; }
  703. }
  704. public override string Namespace
  705. {
  706. get { return innerHeader.Namespace; }
  707. }
  708. public override bool MustUnderstand
  709. {
  710. get { return innerHeader.MustUnderstand; }
  711. }
  712. public override bool Relay
  713. {
  714. get { return innerHeader.Relay; }
  715. }
  716. public override string Actor
  717. {
  718. get { return innerHeader.Actor; }
  719. }
  720. protected override void OnWriteStartHeader(XmlDictionaryWriter writer, MessageVersion messageVersion)
  721. {
  722. //Prefix needed since there may be xsi:type attribute at toplevel with qname value where ns = ""
  723. writer.WriteStartElement((this.Namespace == null || this.Namespace.Length == 0) ? string.Empty : "h", this.Name, this.Namespace);
  724. OnWriteHeaderAttributes(writer, messageVersion);
  725. }
  726. protected virtual void OnWriteHeaderAttributes(XmlDictionaryWriter writer, MessageVersion messageVersion)
  727. {
  728. base.WriteHeaderAttributes(writer, messageVersion);
  729. }
  730. }
  731. internal class XmlElementMessageHeader : OperationFormatterHeader
  732. {
  733. protected XmlElement headerValue;
  734. public XmlElementMessageHeader(OperationFormatter operationFormatter, MessageVersion version, string name, string ns, bool mustUnderstand, string actor, bool relay, XmlElement headerValue) :
  735. base(operationFormatter, version, name, ns, mustUnderstand, actor, relay)
  736. {
  737. this.headerValue = headerValue;
  738. }
  739. protected override void OnWriteHeaderAttributes(XmlDictionaryWriter writer, MessageVersion messageVersion)
  740. {
  741. base.WriteHeaderAttributes(writer, messageVersion);
  742. XmlDictionaryReader nodeReader = XmlDictionaryReader.CreateDictionaryReader(new XmlNodeReader(headerValue));
  743. nodeReader.MoveToContent();
  744. writer.WriteAttributes(nodeReader, false);
  745. }
  746. protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
  747. {
  748. headerValue.WriteContentTo(writer);
  749. }
  750. }
  751. internal struct QName
  752. {
  753. internal string Name;
  754. internal string Namespace;
  755. internal QName(string name, string ns)
  756. {
  757. Name = name;
  758. Namespace = ns;
  759. }
  760. }
  761. internal class QNameComparer : IEqualityComparer<QName>
  762. {
  763. static internal QNameComparer Singleton = new QNameComparer();
  764. QNameComparer() { }
  765. public bool Equals(QName x, QName y)
  766. {
  767. return x.Name == y.Name && x.Namespace == y.Namespace;
  768. }
  769. public int GetHashCode(QName obj)
  770. {
  771. return obj.Name.GetHashCode();
  772. }
  773. }
  774. internal class MessageHeaderDescriptionTable : Dictionary<QName, MessageHeaderDescription>
  775. {
  776. internal MessageHeaderDescriptionTable() : base(QNameComparer.Singleton) { }
  777. internal void Add(string name, string ns, MessageHeaderDescription message)
  778. {
  779. base.Add(new QName(name, ns), message);
  780. }
  781. internal MessageHeaderDescription Get(string name, string ns)
  782. {
  783. MessageHeaderDescription message;
  784. if (base.TryGetValue(new QName(name, ns), out message))
  785. return message;
  786. return null;
  787. }
  788. }
  789. }
  790. }