private object DeserializeQueueMessage(CloudQueueMessage queueMsg, Type destType) { using (MemoryStream messageData = new MemoryStream(queueMsg.AsBytes)) { try { long dataLength = messageData.Length; object msgObject = this.dataSerializer.Deserialize(messageData, destType); // If successful, verify whether or not we are dealing with a small message of type XElement or XDocument. This is because the de-serialization from these types // will not reliably detect the serialized instances of LargeQueueMessageInfo and will return them as either XElement or XDocument. if (CloudUtility.IsAllowedQueueMessageSize(dataLength) && (destType == typeof(XDocument) || destType == typeof(XElement))) { // Both XElement and XDocument share the same base class of type XNode, hence we can safely cast to this type. XNode xmlMsgObject = msgObject as XNode; if (xmlMsgObject != null) { using (XmlReader xmlReader = xmlMsgObject.CreateReader()) { xmlReader.MoveToContent(); // If the first node's name matches the name of the LargeQueueMessageInfo type, // we should treat this message as an instance of LargeQueueMessageInfo and perform de-serialization one more time. if (String.Compare(xmlReader.Name, typeof(LargeQueueMessageInfo).Name, false) == 0) { messageData.Seek(0, SeekOrigin.Begin); msgObject = this.dataSerializer.Deserialize(messageData, typeof(LargeQueueMessageInfo)); } } } } return(msgObject); } catch (SerializationException) { // Got a serialization exception, should reset the stream position. messageData.Seek(0, SeekOrigin.Begin); } // Try to deserialize as LargeQueueMessageInfo. return(this.dataSerializer.Deserialize(messageData, typeof(LargeQueueMessageInfo))); } }
/// <summary> /// Puts a single message on a queue. /// </summary> /// <typeparam name="T">The type of the payload associated with the message.</typeparam> /// <param name="queueName">The target queue name on which message will be placed.</param> /// <param name="message">The payload to be put into a queue.</param> public void Put <T>(string queueName, T message) { Guard.ArgumentNotNullOrEmptyString(queueName, "queueName"); Guard.ArgumentNotNull(message, "message"); // Obtain a reference to the queue by its name. The name will be validated against compliance with storage resource names. var queue = this.queueStorage.GetQueueReference(CloudUtility.GetSafeContainerName(queueName)); CloudQueueMessage queueMessage = null; // Allocate a memory buffer into which messages will be serialized prior to being put on a queue. using (MemoryStream dataStream = new MemoryStream(Convert.ToInt32(CloudQueueMessage.MaxMessageSize))) { // Perform serialization of the message data into the target memory buffer. this.dataSerializer.Serialize(message, dataStream); // Reset the position in the buffer as we will be reading its content from the beginning. dataStream.Seek(0, SeekOrigin.Begin); // First, determine whether the specified message can be accommodated on a queue. if (CloudUtility.IsAllowedQueueMessageSize(dataStream.Length)) { queueMessage = new CloudQueueMessage(dataStream.ToArray()); } else { // Create an instance of a large queue item metadata message. LargeQueueMessageInfo queueMsgInfo = LargeQueueMessageInfo.Create(queueName); // Persist the stream of data that represents a large message into the overflow message store. this.overflowStorage.Put <Stream>(queueMsgInfo.ContainerName, queueMsgInfo.BlobReference, dataStream); // Invoke the Put operation recursively to enqueue the metadata message. Put <LargeQueueMessageInfo>(queueName, queueMsgInfo); } } // Check if a message is available to be put on a queue. if (queueMessage != null) { Put(queue, queueMessage); } }