Очередь хранилища Azure — разные типы CloudQueueMessage

У меня есть очередь в хранилище Azure, и я хочу иметь возможность добавлять в нее различные типы сообщений и анализировать их как конкретные типы.

Например.

public class Customer
{
   public Customer()
   {
   }

   public string Name { get; set;}
   public string Email { get; set;}
   public string Address { get; set;}
}

public class Employee
{
   public Employee()
   {
   }

   public string Id { get; set;}
   public string Name { get; set;}
   public string Email { get; set;}
}

Я могу сериализовать их в JSON и добавить в очередь, но как я могу десериализовать их в их конкретные типы, не зная типа сообщения?

Как я узнаю, что следующее сообщение — «Клиент» или «Сотрудник»? Могу ли я добавить к сообщению какое-то свойство, говорящее: «Это клиент» или «Это сотрудник»…

Потому что у меня есть рабочая роль, которая будет искать сообщения в очереди и выполнять определенные действия в зависимости от типа

get message from queue

If message = customer
  do this
else if message = employee
  do that
else 
  do nothing

person David Dury    schedule 02.07.2014    source источник


Ответы (3)


Я делал это в прошлом. Я записал тип объекта в виде строки в сообщение, затем добавил некоторый символ-разделитель: #, затем добавил сериализованную строку json.

Таким образом, мое сообщение будет выглядеть так:

MyProject.Domain.Model.Product#{'Id':'42','ProductName':'SuperHumanEnchancer'}

а на обратном пути вы читаете все, что стоит перед символом разделителя, и обрабатываете его как имя типа. Строка после символа разделителя будет вашей json-сериализованной строкой.

person trailmax    schedule 03.07.2014

Я сделал следующее в проекте.

Сохраните тип сообщения как свойство BrokeredMessage (где entity — это класс, который я хочу отправить):

var msg = new BrokeredMessage(entity);
msg.ContentType = entity.GetType().AssemblyQualifiedName;
myClient.Send(msg);

У получателя у меня есть этот метод расширения, чтобы получить сообщение правильного типа:

public static object GetBodyOfType(this BrokeredMessage msg)
{
    var ofType = Type.GetType(msg.ContentType);
    var method = typeof(BrokeredMessage).GetMethod("GetBody", new Type[] { });
    var generic = method.MakeGenericMethod(ofType);
    return generic.Invoke(msg, null);
}

Мой фактический получатель делает это (receivedMessage это BrokeredMessage):

var msg = receivedMessage.GetBodyOfType();

что дает мне msg того типа, который я поставил в очередь.

Шаблон, который я использую, похож на то, что вы описываете. Я ставлю команды в очередь на ServiceBus и имею одну рабочую роль, которая обрабатывает любую команду, полученную через обработчик команд. До сих пор это работает очень хорошо.

РЕДАКТИРОВАТЬ: я только что понял, что вы упомянули очереди хранения, тогда как это то, что я использую для служебной шины. Надеюсь, решение будет применено.

person Brendan Green    schedule 02.07.2014
comment
Ваше решение применимо, за исключением того, что ему нужно создать свой собственный тип данных оболочки. Оболочка может предоставлять информацию о типе сообщения точно так же, как это делает тип BrokeredMessage. - person RMD; 03.07.2014

Клиентская библиотека службы хранилища Azure не предоставляет явную поддержку десериализации сообщений очереди. Следовательно, проверьте сериализатор, который вы используете для этого. Например, если вы используете DataContractSerializer, вы можете использовать известные типы для обработки наследования во время сериализации/десериализации.

person Serdar Ozler    schedule 03.07.2014