The idea behind MQContract is to wrap the interactions with multiple MQ server types (ie KubeMQ, NATS.io, Kafka ...) in a simple and easy to use interface.
This is done through defining Messages (classes) and tagging them appropriately as necessary, then using those to interact with a ContractConnection. Using this concept
you can create a general library that contains all your Message classes (contract definitions) that are expected to be transmitted and recieved within a system.
In addition to this, there is also the ability to specify versions for a given message type and implementing converters for original message types to the new
types. This is in line with the idea of not breaking a contract within a system by updating a listener and giving time to other developers/teams to update
their systems to supply the new version of the message. By default all message body's are json encoded (unless they are simple items such as bool or string then they are directly binary encoded)
and unencrypted, all of which can be overridden on a
global level or on a per message type level through implementation of the appropriate interfaces.
Follow these steps to quickly get started with MQContract using the InMemory connector for a simple example.
-
Install the required NuGet packages:
dotnet add package MQContract.Abstractions dotnet add package MQContract.Core dotnet add package MQContract.InMemory
-
Define your message classes:
using MQContract.Attributes; [Message(channel: "Arrivals")] public record ArrivalAnnouncement(string FirstName, string LastName);
-
Create a connection and interact:
using MQContract; using MQContract.InMemory; var serviceConnection = new Connection(); var contractConnection = ContractConnection.Instance(serviceConnection); // Subscribe to messages await contractConnection.SubscribeAsync<ArrivalAnnouncement>( (message) => { Console.WriteLine($"Arrival: {message.Message.FirstName} {message.Message.LastName}"); return ValueTask.CompletedTask; }, (error) => Console.WriteLine($"Error: {error.Message}") ); // Publish a message var result = await contractConnection.PublishAsync(new ArrivalAnnouncement("John", "Doe")); Console.WriteLine($"Published: {result.ID}");
For more advanced usage, including query/response patterns, middleware, and other connectors, explore the Samples section below.
Below is a sample performance benchmarking to indicate how small the effect is on using MQContract vs directly connecting to a service as well as comparisons with using the Source Generated MessageContext vs without.

Practical examples demonstrating MQContract usage with various connectors: