HelloWorld-Beispiel zum senden eines Objekts über RabbitMQ über EasyNetQ zwischen zwei verschiedenen Anwendungen
Hallo, ich bin versucht, senden Sie einen einfachen Gegenstand, wie durch RabbitMQ über EasyNetQ. Habe ich Probleme, zu Deserialisieren das Objekt auf der Abo-Seite. Jemand in der Lage mir zu zeigen, ein Beispiel, wie dies funktioniert. Halten Sie im Verstand das Objekt gesendet wird, ist definiert, es ist ein eigenes Projekt und nicht gemeinsam unter dem Verleger und dem Abonnenten. Hier ist mein Beispiel, und vielleicht können Sie mir sagen, was ist falsch mit ihm?
Programm Ein:
class ProgramA
{
static void Main(string[] args)
{
using (var bus = RabbitHutch.CreateBus("host=localhost"))
{
Console.WriteLine("Press any key to send the message");
Console.ReadKey();
bus.Publish(new MessageA { Text = "Hello World" });
Console.WriteLine("Press any key to quit");
Console.ReadKey();
}
}
public class MessageA
{
public string Text { get; set; }
}
}
Programm B:
class ProgramB
{
static void Main(string[] args)
{
using (var bus = RabbitHutch.CreateBus("host=localhost"))
{
bus.Subscribe<MessageB>("", HandleClusterNodes);
Console.WriteLine("Press any key to quit");
Console.ReadKey();
}
}
private static void HandleClusterNodes(MessageB obj)
{
Console.WriteLine(obj.Text);
}
[Queue("TestMessagesQueue", ExchangeName = "EasyNetQSample.ProgramA+MessageA:EasyNetQSample")]
public class MessageB
{
public string Text { get; set; }
}
}
Ist hier der Fehler ich erhalte:
DEBUG: HandleBasicDeliver on consumer: f9ded52d-039c-411a-9b9f-5c8ee3301854, deliveryTag: 1
DEBUG: Received
RoutingKey: ''
CorrelationId: 'ec41faea-a0c8-4ffd-8163-2cbf85d45fcd'
ConsumerTag: 'f9ded52d-039c-411a-9b9f-5c8ee3301854'
DeliveryTag: 1
Redelivered: False
ERROR: Exception thrown by subscription callback.
Exchange: 'EasyNetQSample.ProgramA+MessageA:EasyNetQSample'
Routing Key: ''
Redelivered: 'False'
Message:
{"Text":"Hello World"}
BasicProperties:
ContentType=NULL, ContentEncoding=NULL, Headers=[], DeliveryMode=2, Priority=0, CorrelationId=ec41faea-a0c8-4ffd-8163-2cbf85d45fcd, ReplyTo=NULL, Expiration=NULL, MessageId=NULL, Timestamp=0, Type=EasyNetQSample.ProgramA+MessageA:EasyNetQSample, UserId=NULL, AppId=NULL, ClusterId=NULL
Exception:
System.AggregateException: One or more errors occurred. ---> EasyNetQ.EasyNetQException: Cannot find type EasyNetQSample.ProgramA+MessageA:EasyNetQSample
at EasyNetQ.TypeNameSerializer.DeSerialize(String typeName)
at EasyNetQ.DefaultMessageSerializationStrategy.DeserializeMessage(MessageProperties properties, Byte[] body)
at EasyNetQ.RabbitAdvancedBus.<>c__DisplayClass19.<Consume>b__18(Byte[] body, MessageProperties properties, MessageReceivedInfo messageReceivedInfo)
at EasyNetQ.RabbitAdvancedBus.<>c__DisplayClass1e.<Consume>b__1d(Byte[] body, MessageProperties properties, MessageReceivedInfo receviedInfo)
at EasyNetQ.Consumer.HandlerRunner.InvokeUserMessageHandler(ConsumerExecutionContext context)
--- End of inner exception stack trace ---
---> (Inner Exception #0) EasyNetQ.EasyNetQException: Cannot find type EasyNetQSample.ProgramA+MessageA:EasyNetQSample
at EasyNetQ.TypeNameSerializer.DeSerialize(String typeName)
at EasyNetQ.DefaultMessageSerializationStrategy.DeserializeMessage(MessageProperties properties, Byte[] body)
at EasyNetQ.RabbitAdvancedBus.<>c__DisplayClass19.<Consume>b__18(Byte[] body, MessageProperties properties, MessageReceivedInfo messageReceivedInfo)
at EasyNetQ.RabbitAdvancedBus.<>c__DisplayClass1e.<Consume>b__1d(Byte[] body, MessageProperties properties, MessageReceivedInfo receviedInfo)
at EasyNetQ.Consumer.HandlerRunner.InvokeUserMessageHandler(ConsumerExecutionContext context)<---
Was muss ich tun, um der Lage, richtig zu Deserialisieren MessageA
?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Soweit ich weiß, die Standard Einstellung der EasyNetQ erfordert den Typ des serialisierten Objekts konsistent zwischen den Anwendungen. Zum Beispiel, können Sie schicken jedem bekannt .NET einfach, wie String:
und es wird glücklich sein auf beide Projekte.
Können Sie Ihre eigene Mitteilung, wenn Sie legen Sie es auf eine gemeinsamen Bibliothek (dll). Da du speziell erwähnt, dass Sie befinden sich in verschiedenen Projekten, würde ich vorschlagen, zu serialisieren und gegossene Objekte selbst.
EasyNetQ verwendet, da er intern Newtonsoft Json.NET Objekte serialisieren, wie diese. Wie Sie sehen können, wurde die Nachricht serialisiert bereits als:
Dies selbst zu tun, müssen Sie noch einen Verweis hinzufügen Json.NET da EasyNetQ versteckt sich dieser Bezug durch die Verwendung ilrepack.
Sollte dies funktionieren:
und
Aber verlieren Sie Ihre Attribut-basiertes routing mit dieser und vielleicht möchten ändern Sie Ihre Methoden.
Wenn Sie möchten, dass Sie basic Methoden, Sie können Thema, wie dieses:
Aber komplette Steuern, müssen Sie verwenden Erweiterte API;
und auf dem Abonnenten-Teil:
ist das fast gleiche wie das original RabbitMQ C# Client-API.
Detaillierte Analyse:
Das Hauptproblem ist diese Ausnahme:
Diese wird ausgelöst durch EasyNetQ, weil es nicht finden können, die der besonderen Klasse auf dem endpoint.
Wenn wir uns an der Quelle-code der TypeNameSerializer.cs, werden Sie sehen,
dies ist, wo es versucht, zu finden EasyNetQSample.ProgramA.NachrichtEine Typ auf zweiten Projekt, wenn Sie nur weiß, EasyNetQSample.ProgramB.NachrichtB.
Alternativ können Sie roll-out Ihrer eigenen ISerializer oder einen ITypeNameSerializer in der Standard - serializer aber ich habe nicht versucht, diese.
Klasse
MessageA
müssen in den Geltungsbereich der beiden appsFurkan ist richtig, dass dein problem ist, dass der Teilnehmer Zugriff auf die Bedürfnisse
MessageA
Art definiert sich durch Ihren Verleger, so dass es Deserialisieren der Nachricht zu geben. Aus der EasyNetQ docsDiese Beträge, die zu einem engen gemeinsamen Vertrag zwischen publisher und consumer. Wenn Sie möchten, um Sie zu lockern, dass bis dann es gibt ein paar Dinge, die Sie tun können:
Können Sie veröffentlichen und abonnieren basiert auf einer Schnittstelle (z.B.
IMessage
, aus denen Sie ableiten könnenMessageA
). Sie werden immer noch Zugriff auf dieMessageA
geben, um die Besetzung der empfangenen Nachricht, aber Sie können veröffentlichen und abonnieren Sie ohne die Angabe eines bestimmten abgeleiteten Typ.Können Sie erstellen, die einen einzigen, gemeinsamen "container" - Typ (z.B.
MessageContainer
) und dann serialisieren/Deserialisieren Ihres Typs in eine Instanz des container-Typs als XML, JSON, was auch immer. Ihre Abonnenten können ziehen Sie die Daten aus dem container und analysiert werden, doch es will. Man könnte auch ein schema oder version info in den container-header zu geben, einige Hinweise auf den Abonnenten über, wie man die Daten analysieren. Der Punkt, dass Sie nie schalten Sie es in einen definierten Typ und brauchen deshalb keinen Zugriff auf einen Haufen von Typen, die nur auf dieMessageContainer
geben, so können Sie bei den serialisierten Inhalt.