2015-07-20 4 views
0

У меня есть компонент, который записывает в очередь (вот код):MSMQ с помощью BinaryFormatter

using (MessageQueueTransaction transaction = new MessageQueueTransaction()) 
      { 
       transaction.Begin(); 
       using (var queue = new MessageQueue(@fullQueue, QueueAccessMode.Send)) 
       { 
        BinaryMessageFormatter formatter = new BinaryMessageFormatter(); 
        // XmlMessageFormatter formatter = new XmlMessageFormatter(new Type[] { typeof(Testing) }); 

        var testing = new Testing {myBody = string.Format("Hello {0}",Environment.UserName), myMessageText = "Header"}; 
        var message = new Message 
        { 
         Body = testing, 
         Label = Environment.MachineName, 
         UseDeadLetterQueue = true, 
         Recoverable = true, 
         Formatter = formatter 
        }; 
        queue.Send(message, MessageQueueTransactionType.Single); 

       } 
       transaction.Commit(); 

      } 

Теперь, когда я запускаю выше «Тестирование» просто Serializble объект с 2-мя свойствами на нем. Если я посмотрю на текст текста в очереди, он выглядит нормально.

Теперь у меня есть отдельный компонент для чтения из очереди:

BinaryMessageFormatter formatter = new BinaryMessageFormatter(); 
     // XmlMessageFormatter formatter = new XmlMessageFormatter(new Type[] { typeof(Testing) }); 
     MessageQueue msgQ = new MessageQueue(fullQueue, QueueAccessMode.Receive); 

     try 
     { 

      using (TransactionScope transaction = new TransactionScope()) 
      { 

       Message incoming = new Message { Formatter = formatter, AcknowledgeType = AcknowledgeTypes.FullReceive }; 

       incoming = msgQ.Receive(new TimeSpan(0, 0, 3),MessageQueueTransactionType.Single); 
       // var ttt = incoming.Body; 
       MemoryStream mem = (MemoryStream) incoming.BodyStream; 
       mem.Seek(0, SeekOrigin.Begin); 
       IFormatter ifm = new BinaryFormatter(); 
       Testing tt = (Testing)ifm.Deserialize(mem); 

       transaction.Complete(); 
      } 

     } 

Теперь в точке я выступаю в ifm.Deserialize, это ошибки с

Не удается найти сборку «MSMQWrite , Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null ' Где MSMQWrite - это имя метода в моем компоненте записи.

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

var testing = new Testing {myBody = string.Format("Hello {0}",Environment.UserName), myMessageText = "Header"}; 
        MemoryStream mem = new MemoryStream(); 

        BinaryFormatter bf = new BinaryFormatter(); 
        bf.Serialize(mem,testing); 

        var message = new Message 
        { BodyStream = mem, 
         //Body = testing, 
         Label = Environment.MachineName, 
         UseDeadLetterQueue = true, 
         Recoverable = true, 
         Formatter = formatter 
        }; 
        queue.Send(message, MessageQueueTransactionType.Single); 

Как вы можете видеть, я устанавливаю BodyStream прямо сейчас, но я все равно получаю ту же ошибку при попытке чтения из очереди.

+0

У вас есть отдельный класс тестирования в каждой сборке? Если вы хотите использовать двоичный форматировщик, тогда сборки должны быть общими (если вы не хотите _play_ с ним, возможно, просто не легко) –

+0

Да, класс тестирования был дублирован в обеих сборках – bilpor

+0

Вы не можете в C# (напротив, например, на C++), класс привязан к его сборке. Имя недостаточно. Вы должны перенести его на общую сборку (или _hacking_ formatter, чтобы разрешить ** другой тип **, потому что класс с таким же именем является другой сборкой другого типа) –

ответ

0

Вам необходимо ссылаться на сборку, которая содержит класс тестирования, от вашего второго компонента. Я предполагаю, что сборка - это MSMQWrite. Если вы уже ссылаетесь на нее, убедитесь, что она копируется в папку, из которой выполняется второй компонент, поэтому ее можно найти во время выполнения.

Другой вариант заключается в перемещении фактического класса, который сериализуется на другой компонент (например, MSMQCommon), и ссылается на него как на запись компонента, так и на одно чтение. Или просто один компонент.

+0

Я не понимаю, почему мне нужно было иметь оба метода в единственная сборка. Все дело в том, что в живой среде у меня есть 1 компонент, установленный на отправляющем сервере, а другой на принимающем сервере полностью отдельные физические машины. При создании одного компонента и развертывании дважды, чтобы каждый мог использовать правильный метод, явно ошибочно. Я предполагал, что сообщение об ошибке вводит в заблуждение и что это что-то еще, что мне не хватает. Единственное, что связывает компоненты, это очередь сообщений. В отношении одного метода компонентов не требуется ссылаться на метод других компонентов. – bilpor

+0

Вы используете Binary Formatter, поэтому для десериализации вам нужна сборка, содержащая тот же самый объект, который вы сериализуете, следовательно, общий компонент (или все в том же). Все в одном компоненте было всего лишь небольшим достижением. Если вы хотите отделить от общего класса ваши компоненты, вам понадобится использовать другой Сериализатор, XML или пользовательский, и ваши классы в обоих направлениях знают, как сериализовать. Тем не менее, перенос DTO на общий компонент и его развертывание в обоих направлениях. – Juan

+0

Привет, я понял, что вы имели в виду. DTO нужно поместить в свою собственную сборку, а затем ссылаться как на отправитель, так и на приемник dll, теперь это работает. – bilpor

Смежные вопросы