在Azure队列存储中传递对象消息
我正在尝试找到一种将对象传递给Azure队列的方法。 我找不到办法做到这一点。
正如我所见,我可以传递字符串或字节数组,这对于传递对象来说并不是很舒服。
无论如何将自定义对象传递给队列?
谢谢!
您可以使用以下类作为示例:
[Serializable] public abstract class BaseMessage { public byte[] ToBinary() { BinaryFormatter bf = new BinaryFormatter(); byte[] output = null; using (MemoryStream ms = new MemoryStream()) { ms.Position = 0; bf.Serialize(ms, this); output = ms.GetBuffer(); } return output; } public static T FromMessage(CloudQueueMessage m) { byte[] buffer = m.AsBytes; T returnValue = default(T); using (MemoryStream ms = new MemoryStream(buffer)) { ms.Position = 0; BinaryFormatter bf = new BinaryFormatter(); returnValue = (T)bf.Deserialize(ms); } return returnValue; } }
然后是StdQueue(强类型的队列):
public class StdQueue where T : BaseMessage, new() { protected CloudQueue queue; public StdQueue(CloudQueue queue) { this.queue = queue; } public void AddMessage(T message) { CloudQueueMessage msg = new CloudQueueMessage(message.ToBinary()); queue.AddMessage(msg); } public void DeleteMessage(CloudQueueMessage msg) { queue.DeleteMessage(msg); } public CloudQueueMessage GetMessage() { return queue.GetMessage(TimeSpan.FromSeconds(120)); } }
然后,您所要做的就是inheritanceBaseMessage:
[Serializable] public class ParseTaskMessage : BaseMessage { public Guid TaskId { get; set; } public string BlobReferenceString { get; set; } public DateTime TimeRequested { get; set; } }
并创建一个与该消息一起使用的队列:
CloudStorageAccount acc; if (!CloudStorageAccount.TryParse(connectionString, out acc)) { throw new ArgumentOutOfRangeException("connectionString", "Invalid connection string was introduced!"); } CloudQueueClient clnt = acc.CreateCloudQueueClient(); CloudQueue queue = clnt.GetQueueReference(processQueue); queue.CreateIfNotExist(); this._queue = new StdQueue(queue);
希望这可以帮助!
使用Newtonsoft.Json和async的扩展方法
public static async Task AddMessageAsJsonAsync(this CloudQueue cloudQueue, T objectToAdd) { var messageAsJson = JsonConvert.SerializeObject(objectToAdd); var cloudQueueMessage = new CloudQueueMessage(messageAsJson); await cloudQueue.AddMessageAsync(cloudQueueMessage); }
我喜欢这种泛化方法,但我不喜欢将Serialize属性放在我可能想要放入消息的所有类中,并从基类派生它们(我可能已经有了基类)所以我用…
using System; using System.Text; using Microsoft.WindowsAzure.Storage.Queue; using Newtonsoft.Json; namespace Example.Queue { public static class CloudQueueMessageExtensions { public static CloudQueueMessage Serialize(Object o) { var stringBuilder = new StringBuilder(); stringBuilder.Append(o.GetType().FullName); stringBuilder.Append(':'); stringBuilder.Append(JsonConvert.SerializeObject(o)); return new CloudQueueMessage(stringBuilder.ToString()); } public static T Deserialize(this CloudQueueMessage m) { int indexOf = m.AsString.IndexOf(':'); if (indexOf <= 0) throw new Exception(string.Format("Cannot deserialize into object of type {0}", typeof (T).FullName)); string typeName = m.AsString.Substring(0, indexOf); string json = m.AsString.Substring(indexOf + 1); if (typeName != typeof (T).FullName) { throw new Exception(string.Format("Cannot deserialize object of type {0} into one of type {1}", typeName, typeof (T).FullName)); } return JsonConvert.DeserializeObject (json); } } }
例如
var myobject = new MyObject(); _queue.AddMessage( CloudQueueMessageExtensions.Serialize(myobject)); var myobject = _queue.GetMessage().Deserialize();
如果存储队列与WebJob或Azurefunction(非常常见的情况)一起使用,则当前的Azure SDK允许直接使用POCO对象。 看这里的例子:
- https://docs.microsoft.com/en-us/sandbox/functions-recipes/queue-storage
- https://github.com/Azure/azure-webjobs-sdk/wiki/Queues#trigger
注意:SDK将自动使用Newtonsoft.Json进行序列化/反序列化。
这不是正确的方法。 队列不是用于存储对象的。 你需要把对象放在blob或table(序列化)中。 我相信队列messgae体有64kb大小限制与sdk1.5和8kb wih较低版本。 Messgae的身体是转移为仅仅提取它的workera的重要数据。