对于T4模板,这是Azure Queue构造的一个好/可取的模式吗?

我正在构建一个T4模板,它将帮助人们以一致和简单的方式构建Azure队列。 我想让这个自我记录,并且有些一致。

  1. 首先我将队列名称放在文件的顶部,队列名称必须是小写的,所以我添加了ToLower()

  2. 公共构造函数使用内置的StorageClient API来访问连接字符串。 我已经看到了许多不同的方法,并希望得到几乎适用于所有情况的东西。 (想法?分享)

  3. 我不喜欢不需要的HTTP请求来检查队列是否已经创建,所以我做的是一个static bool 。 我没有实现Lock(monitorObject),因为我认为不需要。

  4. 而不是使用字符串并使用逗号解析(如大多数MSDN文档)我将对象传递到队列时序列化。

  5. 为了进一步优化,我使用JSON序列化器扩展方法来充分利用8k限制。 不确定编码是否有助于优化此function

  6. 添加了重试逻辑来处理队列中出现的某些情况(请参阅html链接)

  7. 问: “DataContext”是否适用于此类?

  8. 问:以我的方式命名队列行动名称是一种不好的做法吗?

您认为我应该做出哪些其他更改?

 public class AgentQueueDataContext { // Queue names must always be in lowercase // Is named like a const, but isn't one because .ToLower won't compile... static string AGENT_QUEUE_ACTION_NAME = "AgentQueueActions".ToLower(); static bool QueuesWereCreated { get; set; } DataModel.SecretDataSource secDataSource = null; CloudStorageAccount cloudStorageAccount = null; CloudQueueClient cloudQueueClient = null; CloudQueue queueAgentQueueActions = null; static AgentQueueDataContext() { QueuesWereCreated = false; } public AgentQueueDataContext() : this(false) { } public AgentQueueDataContext(bool CreateQueues) { // This pattern of setting up queues is from: // ttp://convective.wordpress.com/2009/11/15/queues-azure-storage-client-v1-0/ // this.cloudStorageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString"); this.cloudQueueClient = cloudStorageAccount.CreateCloudQueueClient(); this.secDataSource = new DataModel.SecretDataSource(); queueAgentQueueActions = cloudQueueClient.GetQueueReference(AGENT_QUEUE_ACTION_NAME); if (QueuesWereCreated == false || CreateQueues) { queueAgentQueueActions.CreateIfNotExist(); QueuesWereCreated = true; } } // This is the method that will be spawned using ThreadStart public void CheckQueue() { while (true) { try { CloudQueueMessage msg = queueAgentQueueActions.GetMessage(); bool DoRetryDelayLogic = false; if (msg != null) { // Deserialize using JSON (allows more data to be stored) AgentQueueEntry actionableMessage = msg.AsString.FromJSONString(); switch (actionableMessage.ActionType) { case AgentQueueActionEnum.EnrollNew: { // Add to break; } case AgentQueueActionEnum.LinkToSite: { // Link within Agent itself // Link within Site break; } case AgentQueueActionEnum.DisableKey: { // Disable key in site // Disable key in AgentTable (update modification time) break; } default: { break; } } // // Only delete the message if the requested agent has been missing for // at least 10 minutes // if (DoRetryDelayLogic) { if (msg.InsertionTime != null) if (msg.InsertionTime < DateTime.UtcNow + new TimeSpan(0, 10, 10)) continue; // ToDo: Log error: AgentID xxx has not been found in table for xxx minutes. // It is likely the result of a the registratoin host crashing. // Data is still consistent. Deleting queued message. } // // If execution made it to this point, then we are either fully processed, or // there is sufficent reason to discard the message. // try { queueAgentQueueActions.DeleteMessage(msg); } catch (StorageClientException ex) { // As of July 2010, this is the best way to detect this class of exception // Description: ttp://blog.smarx.com/posts/deleting-windows-azure-queue-messages-handling-exceptions if (ex.ExtendedErrorInformation.ErrorCode == "MessageNotFound") { // pop receipt must be invalid // ignore or log (so we can tune the visibility timeout) } else { // not the error we were expecting throw; } } } else { // allow control to fall to the bottom, where the sleep timer is... } } catch (Exception e) { // Justification: Thread must not fail. //Todo: Log this exception // allow control to fall to the bottom, where the sleep timer is... // Rationale: not doing so may cause queue thrashing on a specific corrupt entry } // todo: Thread.Sleep() is bad // Replace with something better... Thread.Sleep(9000); } 

问:“DataContext”是否适用于此类?

在.NET中我们有很多DataContext类,所以从某种意义上说,你希望名称能够恰当地传达类的function,我认为XyzQueueDataContext正确地传达类的function – 尽管你无法从中查询。

如果您希望与已接受的模式语言更加一致, 则企业应用程序体系结构模式会调用封装对网关外部系统的访问权限的任何类,而更具体地说,您可能希望在企业集成模式的语言中使用术语“ 通道 ” -这就是我要做的。

问:以我的方式命名队列行动名称是一种不好的做法吗?

嗯,它肯定将队列名称紧密地耦合到类。 这意味着,如果您以后决定要将它们分离,则不能。

作为一般性评论,我认为这个课程可能会因为努力做得更少而受益。 使用队列与管理它不是一回事,因此我不建议 CloudQueue注入到实例中,而是将所有队列管理代码都放在那里。 以下是我实现AzureChannel构造函数的方法:

 private readonly CloudQueue queue; public AzureChannel(CloudQueue queue) { if (queue == null) { throw new ArgumentNullException("queue"); } this.queue = queue; } 

这更符合单一责任原则 ,您现在可以在自己的(可重用)类中实现队列管理。