BinaryMessageFormatter.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. //------------------------------------------------------------------------------
  2. // <copyright file="BinaryMessageFormatter.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. //------------------------------------------------------------------------------
  6. using System;
  7. using System.ComponentModel;
  8. using System.IO;
  9. using System.Runtime.Serialization.Formatters;
  10. using System.Runtime.Serialization.Formatters.Binary;
  11. namespace Experimental.System.Messaging
  12. {
  13. /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter"]/*' />
  14. /// <devdoc>
  15. /// Formatter class that serializes and deserializes objects into
  16. /// and from MessageQueue messages using binary format.
  17. /// </devdoc>
  18. public class BinaryMessageFormatter : IMessageFormatter
  19. {
  20. private BinaryFormatter formatter;
  21. internal const short VT_BINARY_OBJECT = 0x300;
  22. /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter.BinaryMessageFormatter"]/*' />
  23. /// <devdoc>
  24. /// Creates a new Binary message formatter object.
  25. /// </devdoc>
  26. public BinaryMessageFormatter()
  27. {
  28. this.formatter = new BinaryFormatter();
  29. }
  30. /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter.BinaryMessageFormatter1"]/*' />
  31. /// <devdoc>
  32. /// Creates a new Binary message formatter object
  33. /// with the given properties.
  34. /// </devdoc>
  35. public BinaryMessageFormatter(FormatterAssemblyStyle topObjectFormat, FormatterTypeStyle typeFormat)
  36. {
  37. this.formatter = new BinaryFormatter();
  38. this.formatter.AssemblyFormat = topObjectFormat;
  39. this.formatter.TypeFormat = typeFormat;
  40. }
  41. /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter.TopObjectFormat"]/*' />
  42. /// <devdoc>
  43. /// Determines how the top (root) object of a graph
  44. /// is laid out in the serialized stream.
  45. /// </devdoc>
  46. [MessagingDescription(Res.MsgTopObjectFormat), DefaultValueAttribute(FormatterAssemblyStyle.Simple)]
  47. public FormatterAssemblyStyle TopObjectFormat
  48. {
  49. get
  50. {
  51. return this.formatter.AssemblyFormat;
  52. }
  53. set
  54. {
  55. this.formatter.AssemblyFormat = value;
  56. }
  57. }
  58. /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter.TypeFormat"]/*' />
  59. /// <devdoc>
  60. /// Determines how type descriptions are laid out in the
  61. /// serialized stream.
  62. /// </devdoc>
  63. [MessagingDescription(Res.MsgTypeFormat), DefaultValueAttribute(FormatterTypeStyle.TypesWhenNeeded)]
  64. public FormatterTypeStyle TypeFormat
  65. {
  66. get
  67. {
  68. return this.formatter.TypeFormat;
  69. }
  70. set
  71. {
  72. this.formatter.TypeFormat = value;
  73. }
  74. }
  75. /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter.CanRead"]/*' />
  76. /// <devdoc>
  77. /// <para>When this method is called, the formatter will attempt to determine
  78. /// if the contents of the message are something the formatter can deal with.</para>
  79. /// </devdoc>
  80. public bool CanRead(Message message)
  81. {
  82. if (message == null)
  83. throw new ArgumentNullException("message");
  84. int variantType = message.BodyType;
  85. if (variantType != VT_BINARY_OBJECT)
  86. return false;
  87. return true;
  88. }
  89. /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter.Clone"]/*' />
  90. /// <devdoc>
  91. /// This method is needed to improve scalability on Receive and ReceiveAsync scenarios. Not requiring
  92. /// thread safety on read and write.
  93. /// </devdoc>
  94. public object Clone()
  95. {
  96. return new BinaryMessageFormatter(TopObjectFormat, TypeFormat);
  97. }
  98. /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter.Read"]/*' />
  99. /// <devdoc>
  100. /// This method is used to read the contents from the given message
  101. /// and create an object.
  102. /// </devdoc>
  103. public object Read(Message message)
  104. {
  105. if (message == null)
  106. throw new ArgumentNullException("message");
  107. int variantType = message.BodyType;
  108. if (variantType == VT_BINARY_OBJECT)
  109. {
  110. Stream stream = message.BodyStream;
  111. return formatter.Deserialize(stream);
  112. }
  113. throw new InvalidOperationException(Res.GetString(Res.InvalidTypeDeserialization));
  114. }
  115. /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter.Write"]/*' />
  116. /// <devdoc>
  117. /// This method is used to write the given object into the given message.
  118. /// If the formatter cannot understand the given object, an exception is thrown.
  119. /// </devdoc>
  120. public void Write(Message message, object obj)
  121. {
  122. if (message == null)
  123. throw new ArgumentNullException("message");
  124. Stream stream = new MemoryStream();
  125. formatter.Serialize(stream, obj);
  126. message.BodyType = VT_BINARY_OBJECT;
  127. message.BodyStream = stream;
  128. }
  129. }
  130. }