Summary
This is a simple example showing how to implement a communication scenario where one application sends notifications to other applications.
CodeProject
Introduction
The scenario where one application needs to inform other applications about some particular event is very common.
The application that wants to be informed about events subscribes to get notification messages from the publishing application. Then, when the event occurs, the publishing application notifies all subscribed applications.
The example below shows how to implement this scenario using Eneter Messaging Framework
.
(The framework is free and can be downloaded from www.eneter.net. The online help for developers can be found at http://www.eneter.net/OnlineHelp/EneterMessagingFramework/Index.html.)
Publisher
The publishing application in our example is very simple. It provides just three events that are invoked when the button is clicked.
To publish these events, the publisher uses the Broker
component. The broker component receives messages via the input channel and forwards them to all subscribed receivers.
In our scenario we want, the broker receives the message when the button is clicked and then forwards it to subscribed receivers.
Therefore we need that our broker can communicate two ways:
- Internally - to receive internal messages (from the same process) when the 'Notify' button is clicked.
- Interprocess - to register/unregister subscribers and to forward notifications to subscribers.
To enable the communication via 2 different channels, we can use the
Dispatcher
component.
The dispatcher receives messages and forwards them to all attached receivers. In our case, the dispatcher receives messages from two channels (internal messages and interprocess messages) and forwards them to only one receiver -
Broker
.
The whole implementation is very simple:
using System;
using System.Windows.Forms;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.Infrastructure.ConnectionProvider;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.SynchronousMessagingSystem;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.Nodes.Broker;
using Eneter.Messaging.Nodes.Dispatcher;
namespace Publisher
{
public partial class Form1 : Form
{
public class NotifyMsg1
{
public DateTime CurrentTime { get; set; }
}
public class NotifyMsg2
{
public int Number { get; set; }
}
public class NotifyMsg3
{
public string TextMessage { get; set; }
}
public Form1()
{
InitializeComponent();
IMessagingSystemFactory anInternalMessaging =
new SynchronousMessagingSystemFactory();
IDuplexBrokerFactory aBrokerFactory =
new DuplexBrokerFactory(new XmlStringSerializer());
myBroker = aBrokerFactory.CreateBroker();
myBrokerClient = aBrokerFactory.CreateBrokerClient();
IDuplexDispatcherFactory aDispatcherFactory =
new DuplexDispatcherFactory(anInternalMessaging);
myDispatcher = aDispatcherFactory.CreateDuplexDispatcher();
IConnectionProviderFactory aConnectionProviderFactory =
new ConnectionProviderFactory();
IConnectionProvider aConnectionProvider =
aConnectionProviderFactory.CreateConnectionProvider(anInternalMessaging);
aConnectionProvider.Attach(myBroker, "MyBrokerChannelId");
myDispatcher.AddDuplexOutputChannel("MyBrokerChannelId");
aConnectionProvider.Connect
(myDispatcher, myBrokerClient, "MyInternalDispatcherChannelId");
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel aTcpInputChannel =
aMessaging.CreateDuplexInputChannel("127.0.0.1:8091");
myDispatcher.AttachDuplexInputChannel(aTcpInputChannel);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
myDispatcher.DetachDuplexInputChannel();
}
private void Notify1Btn_Click(object sender, EventArgs e)
{
NotifyMsg1 aMsg = new NotifyMsg1();
aMsg.CurrentTime = DateTime.Now;
object aSerializedMsg = mySerializer.Serialize<NotifyMsg1>(aMsg);
myBrokerClient.SendMessage("MyNotifyMsg1", aSerializedMsg);
}
private void Notify2Btn_Click(object sender, EventArgs e)
{
NotifyMsg2 aMsg = new NotifyMsg2();
aMsg.Number = 12345;
object aSerializedMsg = mySerializer.Serialize<NotifyMsg2>(aMsg);
myBrokerClient.SendMessage("MyNotifyMsg2", aSerializedMsg);
}
private void Notify3Btn_Click(object sender, EventArgs e)
{
NotifyMsg3 aMsg = new NotifyMsg3();
aMsg.TextMessage = "My notifying text message.";
object aSerializedMsg = mySerializer.Serialize<NotifyMsg3>(aMsg);
myBrokerClient.SendMessage("MyNotifyMsg3", aSerializedMsg);
}
private IDuplexBroker myBroker;
private IDuplexDispatcher myDispatcher;
private IDuplexBrokerClient myBrokerClient;
private XmlStringSerializer mySerializer = new XmlStringSerializer();
}
}
Subscriber
The subscribing application in this example is very simple too. It can subscribe and unsubscribe via the button and simply displays the incoming notification messages.
To subscribe, unsubscribe and receive messages, the subscriber uses the BrokerClient
component.
The whole implementation is very simple:
using System;
using System.Windows.Forms;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Eneter.Messaging.Nodes.Broker;
namespace Subscriber
{
public partial class Form1 : Form
{
public class NotifyMsg1
{
public DateTime CurrentTime { get; set; }
}
public class NotifyMsg2
{
public int Number { get; set; }
}
public class NotifyMsg3
{
public string TextMessage { get; set; }
}
public Form1()
{
InitializeComponent();
IDuplexBrokerFactory aBrokerFactory =
new DuplexBrokerFactory(new XmlStringSerializer());
myBrokerClient = aBrokerFactory.CreateBrokerClient();
myBrokerClient.BrokerMessageReceived += OnNotificationMessageReceived;
IMessagingSystemFactory aMessagingFactory = new TcpMessagingSystemFactory();
IDuplexOutputChannel anOutputChannel =
aMessagingFactory.CreateDuplexOutputChannel("127.0.0.1:8091");
myBrokerClient.AttachDuplexOutputChannel(anOutputChannel);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
myBrokerClient.DetachDuplexOutputChannel();
}
private void OnNotificationMessageReceived
(object sender, BrokerMessageReceivedEventArgs e)
{
InvokeInUIThread(() =>
{
if (e.ReceivingError == null)
{
if (e.MessageTypeId == "MyNotifyMsg1")
{
NotifyMsg1 aDeserializedMsg =
mySerializer.Deserialize<NotifyMsg1>(e.Message);
Received1TextBox.Text = aDeserializedMsg.CurrentTime.ToString();
}
else if (e.MessageTypeId == "MyNotifyMsg2")
{
NotifyMsg2 aDeserializedMsg =
mySerializer.Deserialize<NotifyMsg2>(e.Message);
Received2TextBox.Text = aDeserializedMsg.Number.ToString();
}
else if (e.MessageTypeId == "MyNotifyMsg3")
{
NotifyMsg3 aDeserializedMsg =
mySerializer.Deserialize<NotifyMsg3>(e.Message);
Received3TextBox.Text = aDeserializedMsg.TextMessage;
}
}
});
}
private void Subscribe1Btn_Click(object sender, EventArgs e)
{
myBrokerClient.Subscribe("MyNotifyMsg1");
}
private void Unsubscribe1Btn_Click(object sender, EventArgs e)
{
Received1TextBox.Text = "";
myBrokerClient.Unsubscribe("MyNotifyMsg1");
}
private void Subscribe2Btn_Click(object sender, EventArgs e)
{
myBrokerClient.Subscribe("MyNotifyMsg2");
}
private void Unsubscribe2Btn_Click(object sender, EventArgs e)
{
Received2TextBox.Text = "";
myBrokerClient.Unsubscribe("MyNotifyMsg2");
}
private void Subscribe3Btn_Click(object sender, EventArgs e)
{
myBrokerClient.Subscribe("MyNotifyMsg3");
}
private void Unsubscribe3Btn_Click(object sender, EventArgs e)
{
Received3TextBox.Text = "";
myBrokerClient.Unsubscribe("MyNotifyMsg3");
}
private void InvokeInUIThread(Action uiMethod)
{
if (InvokeRequired)
{
Invoke(uiMethod);
}
else
{
uiMethod();
}
}
private IDuplexBrokerClient myBrokerClient;
private XmlStringSerializer mySerializer = new XmlStringSerializer();
}
}
You can execute more subscribers and subscribe/unsubscribe them for desired events.
I hope you found the article helpful and if you have any questions about Eneter Messaging Framework
, feel free to ask.