Design pattern name for class that defines the flow between interfaces - c#

I have two interfaces, unaware of each other.
public interface IListener
{
event SignalEventHandler SignalReceived;
}
public interface IDevice
{
Task HandleSignalAsync();
}
Rather than making each listener call a device directly or pass listeners into device implementations, I'd like to keep them decoupled and define the flow separately. For example:
public class MyApplicationFlow
{
private readonly IListener _listener;
private readonly IDevice _device;
public MyApplicationFlow(IListener listener, IDevice device)
{
_listener = listener;
_device = device;
_listener.SignalReceived += ListenerOnSignalReceived;
}
private async void ListenerOnSignalReceived(object sender, SignalEventArgs args)
{
try
{
await _device.HandleSignalAsync();
// do more stuff in real scenario
args.ProgressReporter.ReportComplete();
}
catch (Exception ex)
{
args.ProgressReporter.ReportError(ex);
}
}
}
There could be several IDevice and IListener implementations passed into the flow.
The listeners and devices seem to follow the Adaptor pattern. But what about MyApplicationFlow?
A Mediator defines the interactions between components, but here the objects are different types and unaware of the parent class.
A Facade encapsulates several subsystems, but here the subsystems are not hidden; they are injected into the constructor.
I'm not even sure if this would be a Behavioural or Structural pattern.
Is there a common name for a class that defines the flow between objects? Something I can use as a suffix for the class names that follow this pattern e.g. Manager, Coordinator, Connector (preferably something already used in the .NET framework).
Or, as I can't find anything, am I barking up the wrong tree? Is there a better way to achieve this decoupling?

For one thing, based on your names it seems like you have your listener and device backwards. Meaning, you seem to be listening to a signal sent from the listener and sending it to the device which seems backwards. Listeners imply listening to signals not sending signals in my opinion.
But otherwise I think what you have here is just a message passing system. Rather than directly communicating together you have a message dispatcher which receives messages from one component and sends them off to another. If you expand on what you have there rather than having a single device and a single listener you could establish any number of connections. You would then queue incoming messages and dispatch them to listeners based on those connections.
interface IListener {
void send(ISender sender, IMessage message);
}
interface ISender { }
interface IMessage { }
interface IPending {
ISender from;
IMessage message;
}
class Dispatcher {
private Queue<IPending> messages = new Queue<IPending>();
private Dictionary<ISender, List<IListener>> connections = new Dictionary<ISender, List<IListener>>();
public void connect(ISender sender, IListener listener) {
if (connections[sender] == null) {
connections[sender] = new List<IListener>();
}
connections[sender].add(listener);
}
public void remove(ISender sender, IListener listener) { ... } // removes connection from connections
public void send(ISender from, IMessage message) {
messages.push({ from, message });
}
public void next() { // called in a loop, perhaps in a background thread
if (messages.peek()) {
var message = messages.pop();
foreach(var listener in connections[message.from]) {
listener.send(sender, message);
}
}
}
}

My first thought was it sounds like a variant of the observer pattern, except in your case the observer isn't directly observing. I found this variant called Event / Emitter / Target that sounds pretty close. https://github.com/millermedeiros/js-signals/wiki/Comparison-between-different-Observer-Pattern-implementations
Edit--I've actually changed my mind. This is pub-sub messaging. The IDevice classes are sending, the middle class is receiving the messages and the IListener is subscribing.

Related

Generic Payload for Prism Event Aggregator

I am developing an WPF application and tried to design something event driven using Prism's Event Aggregator.
Currently I am trying to implement something like event queue for Prism events.
To do that I want to subscribe related events and pass them to same method but Event Aggregator wants those methods to have same signature with the event.
Example events:
public class TestEvent1 : PubSubEvent<Class1>
{
}
public class TestEvent2 : PubSubEvent<Class2>
{
}
public class TestEvent3 : PubSubEvent<List<Class3>>
{
}
public class TestEvent3 : PubSubEvent<string>
{
}
Subscriptions:
_eventAggregator.GetEvent<TestEvent1>().Subscribe(OnTestEvent1, true);
_eventAggregator.GetEvent<TestEvent2>().Subscribe(OnTestEvent2, true);
_eventAggregator.GetEvent<TestEvent3>().Subscribe(OnTestEvent3, true);
Example callback method:
private void OnTestEvent1(Class1 object1)
{
// do something
}
Since I only receive data when event published, I tried something like this to use as event payload type, but it doesn't look right:
// Payload
public interface IMessage
{
public object Data { get; set; }
public Type Datatype { get; set; }
public PubSubEvent EventType { get; set; }
}
// Events
public class TestEvent1 : PubSubEvent<IMessage>
{
}
public class TestEvent2 : PubSubEvent<IMessage>
{
}
public class TestEvent3 : PubSubEvent<IMessage>
{
}
// Subscriptions
_eventAggregator.GetEvent<TestEvent1>().Subscribe(EventHandler, true);
_eventAggregator.GetEvent<TestEvent2>().Subscribe(EventHandler, true);
_eventAggregator.GetEvent<TestEvent3>().Subscribe(EventHandler, true);
// Callback
private void EventHandler(IMessage payload)
{
// do something
}
Is this viable and how can I improve or change my "generic" payload?
Extra information:
In my scenario I have multiple UDP servers that periodically receives new data, deserialize it to objects and publish events.
Related "managers" subscribed to those events and get triggered when new data received.
My goal is try to implement an event queue like system in my event receiving classes so it will be easier to deal with multithreading issues.
Here are some diagrams that may help me explain myself better:
My architecture:
My "event queue"
This is more of a code-review question, isn't it?
I would very much prefer strong typing, though, and I wouldn't want to build a queue around the event aggregator, that will always be tedious because you never know when new event types show up. Instead, I'd build my own event aggregator with queueing built in (starting from the existing one).
Also, I'd look into dataflow, for example, because the basic working mode of the event aggregator (fire and forget, one sender, multiple or no receivers) doesn't seem to work well with queueing. If you queue at the sender-side, to you wait for one receiver or all? Do you queue when there are no receivers or do you discard then? If you queue at the receiver-side, why bother at all? The receiver can implement the queue on its own.
When you publish an event with a reference to an object, consider these potential problems:
Any listener will be dependent on the type/assembly of the event parameter.
The referenced object will be held for some time. For how long? You don't know.
The referenced object could have been altered/disposed.
Listeners might handle the referenced object on a different thread.
After dealing with PubSubEvent<T> for several years now, I believe there is only one suitable pattern that successfully handles all cases. Publish your event with a unique identifier, e.g. a Guid.
public class MyItemAddedEvent : PubSubEvent<Guid> {}
Then inject a provider wherever you listen for this event:
public class SomeListener
{
private readonly IMyItemProvider myItemProvider;
[ImportingConstructor]
public SomeListener(IEventAggregator eventAggregator,
IMyItemProvider myItemProvider)
{
this.myItemProvider = myItemProvider;
eventAggregator.GetEvent<MyItemAddedEvent>().Subscribe(OnMyItemAdded, true);
}
private void OnMyItemAdded(Guid id)
{
var myItem = myItemProvider.Get(id);
// Do stuff
}
}
Now it is the responsibility of the provider class to deliver a valid and up-to-date object given a unique id.

Publishing decoded messages from a Stream while keeping encapsulation in Rx

I'm new to using Rx and I've been trying to re-write my MVC w/ Service Layer (NOT ASP!) to use this awesome new-fangled Rx. I have a class called Remote which encapsulates a NetworkStream. The Remote uses Rx to listen to bytes from the NetworkStream and once it works out it's received a full message worth of data, it decodes that data into an IMessage.
I get how I can read from the Stream continuously using Rx from inside the Remote, but how do I publish decoded IMessage from that stream to the outside world from the Remote? Am I supposed to use the classic evented style in C# and have the consumers of the events use Observable.FromEvent?
I only ask because I've read around that IObservable is not meant to be implemented anymore.
Am I supposed to use the classic evented style in C# and have the
consumers of the events use Observable.FromEvent?
If you're not positively forced to do so, do not make an API using C# style events. The IObservable<T> is a powerful, generic, widely supported interface which allows us to treat events as first class citizens while easily managing subscriptions. Even if your consumer isn't using Rx, they'll be able to understand and use IObservable<T> more easily than using C# events. What they do with those events is up to them, but the IObservable<T> abstraction is clearer and simpler.
I've read around that IObservable is not meant to be implemented anymore.
It reality, what we mean is that there's probably not reason to implement IObservable<T> on your own, because we have tools to create instances of that type for us.
We have Observable.Create(...) which allows us to create observables from scratch. We have different types of Subjects like Subject<T>, BehaviorSubject<T>, ReplaySubject<T>, etc, which can be used as proxies and allow us to multicast values to multiple consumers, and we have operators which allow us to transform/compose any IObservable<T> into another type or kind of IObservable<T>.
but how do I publish decoded IMessage from that stream to the outside world from the Remote?
You expose an IObservable<T> on your class / interface.
public interface IRemote
{
public IObservable<IMessage> Messages { get; }
}
You could implement this in any number of ways. First, you could make it so each subscription to Messages gets it's own subscription to your underlying logic...
public class Remote : IRemote
{
private IObservable<IMessage> _messages = ...;
public IObservable<IMessage> Message {
get {
return message;
}
}
}
Or you could make sure that there's only ever one subscription to the underlying logic...
public class Remote : IRemote
{
private IObservable<IMessage> _messages = ...;
private IObservable<IMessage> _refCountedMessages
= this._messages
.Publish()
.RefCount();
public IObservable<IMessage> Message {
get {
return this._refCountedMessages;
}
}
}
Or you could make the connection process extremely explicit in nature.
public interface IRemote
{
public IObservable<IMessage> Messages { get; }
public IDisposable Connect();
}
public class Remote : IRemote
{
private IObservable<IMessage> _messages = ...;
private IObservable<IMessage> _connectableMessages
= this._messages
.Publish();
public IObservable<IMessage> Message {
get {
return this._connectableMessages;
}
}
public IDisposable Connect()
{
return this._connectableMessages.Connect();
}
}
I assume you problem is similar to this question How to "reconstruct lines" of data read from SerialPort using Rx?
Instead of getting strings pushed at you that you then change into messages, you will get bytes. No problem, you can use the same WindowBy concept to slice up your sequence of bytes into windows that can then be translated/converted/mapped/whatever into your IMessage.
Building on Christopher Harris' answer. Here is an implementation of his proposed interfaces. The point here is to show that you can expose observable sequences that are just queries built on top of an underlying observable sequence. In this case the Messages sequence is just a query over the network sequence. With layering we get the level of abstraction that the consumer wants.
void Main()
{
var networkStream = new NetworkStream();
var remote = new Remote(networkStream);
remote.GetMessages().Dump("remote.GetMessages()");
}
// Define other methods and classes here
public class NetworkStream
{
//Fake getting bytes off the wire or disk
public IObservable<byte> GetNetworkStream()
{
var text = #"Line 1.
Hello line 2.
3rd and final line!";
return Observable.Zip(
UTF8Encoding.UTF8.GetBytes(text).ToObservable(),
Observable.Interval(TimeSpan.FromMilliseconds(100)),
(character, time)=>character);
}
}
public interface IMessage
{
string Content {get;}
}
public class Message : IMessage
{
public Message(string content)
{
Content = content;
}
public string Content {get; private set;}
}
public interface IRemote
{
IObservable<IMessage> GetMessages();
}
public class Remote : IRemote
{
private readonly NetworkStream _networkStream;
private readonly byte[] _delimiter = UTF8Encoding.UTF8.GetBytes(Environment.NewLine);
public Remote(NetworkStream networkStream)
{
_networkStream = networkStream;
}
public IObservable<IMessage> GetMessages()
{
return _networkStream.GetNetworkStream()
.WindowByExclusive(b => _delimiter.Contains(b))
.SelectMany(window=>window.ToArray().Select(bytes=>UTF8Encoding.UTF8.GetString(bytes)))
.Select(content=>new Message(content));
}
//TODO Add IDispose and clean up your NetworkStream
}
public static class ObservableEx
{
public static IObservable<IObservable<T>> WindowByExclusive<T>(this IObservable<T> input, Func<T, bool> isWindowBoundary)
{
return Observable.Create<IObservable<T>>(o=>
{
var source = input.Publish().RefCount();
var left = source.Where(isWindowBoundary).Select(_=>Unit.Default).StartWith(Unit.Default);
return left.GroupJoin(
source.Where(c=>!isWindowBoundary(c)),
x=>source.Where(isWindowBoundary),
x=>Observable.Empty<Unit>(),
(_,window)=>window)
.Subscribe(o);
});
}
}

Event Handlers and Interfaces

I have an interface called IDataIO:
public interface IDataIO
{
event DataReceivedEvent DataReceived;
//.....more events,methods and properties
}
I also have multiple classes that implement this interface, namely UdpIO, TcpIO, SerialIO.
Now, I have an IO class that allows me to switch between different input/output hardware. Each instance of this class has a CurrentIODevice property, which could be one of SerialIO,UdpIO or TcpIO. When this property is assigned, i attach 1 or more handlers to the DataReceivedEvent so that my GUI is notified when incoming data is received, as well as other classes that need to be notified.
public class IO
{
IDataIO CurrentIODevice;
public IO()
{
SerialIO serial = new SerialIO();
TcpIO tcp = new TcpIO();
UdpIO udp = new UdpIO();
CurrentIODevice = serial;
}
}
I also have a IOManager class that holds multiple IO objects.
public class IOManager
{
List<IO> Ports = new List<IO>();
public IOManager()
{
Ports.Add(new IO());
Ports.Add(new IO());
}
Ports[0].CurrentIODevice = serial;
Ports[0].CurrentIODevice.DataReceivedHandler += MyGuiUpdate;
Ports[0].CurrentIODevice.DataReceivedHandler += MyDataProcessing;
}
My concern (its not an issue atm) is how I am going to change between different IDataIO interfaces at runtime.
What is the effect of, at runtime, performing the following statement:
//i know this is illegal but just to demonstrate
IOManager.Ports[0].CurrentIODevice = tcp;
Will the event handlers still be functioning (and correctly)?
Do i need to unassign the events before the CurrentIODevice is assigned, and then re-assign the handlers again after? If this is the case, I can see this approach getting quite messy, so if anyone has a better approach to this problem I'm all ears :)
No, your handlers will not work because they're attached to the old object. Interfaces provides...an interface to an object, see it as a kind of contract but they're not a different object themselves.
If you need to switch between different implementations of the interface (at run-time) and to keep all handlers working you have to have the same object reference for the interface itself, kind of strategy pattern (more or less).
In your case you may, for example, implement the IDataIO interface in a DataIO object. It'll expose a property (or a method, I think its intent is more clear) to switch between different implementations of that interface (serial, TCP or whatever). It'll be the only one object to attach an event handler to that interface (and it'll drop the handler when the concrete implementation will change). Users of that object will always see it, whatever it's the concrete implementation it's using.
Example
This is a small example to explain this concept. The generic interface is this:
interface IDataIO
{
void Write(byte[] data);
byte[] Read();
event EventHandler DataReceived;
}
This is the concrete implementation of IDataIO, other classes will use only this class directly:
sealed class DataIO : IDataIO
{
public void SetChannel(IDataIO concreteChannel)
{
if (_concreteChannel != null)
_concreteChannel.DataReceived -= OnDataReceived;
_concreteChannel = concreteChannel;
_concreteChannel.DataReceived += OnDataReceived;
}
public void Write(byte[] data)
{
_concreteChannel.Write(data);
}
public byte[] Read()
{
return _concreteChannel.Read();
}
public event EventHandler DataReceived;
private IDataIO _concreteChannel;
private void OnDataReceived(object sender, EventArgs e)
{
EventHandler dataReceived = DataReceived;
if (dataReceived != null)
dataReceived(this, e);
}
}
Finally some code for testing:
class Test
{
public Test()
{
_channel = new TcpIO();
_channel.DataReceived += OnDataReceived;
}
public void SetChannel(IDataIO channel)
{
_channel.SetChannel(channel);
// Nothing will change for this "user" of DataIO
// but now the channel used for transport will be
// the one defined here
}
private void OnDataReceived(object sender, EventArgs e)
{
// You can use this
byte[] data = ((IDataIO)sender).Read();
// Or this, the sender is always the concrete
// implementation that abstracts the strategy in use
data = _channel.Read();
}
private DataIO _channel;
}
Obviously you should consider the strategy pattern. I will post the code first and explain later:
public interface IDataIO
{
event DataReceivedEvent DataReceived;
//this the new added method that each IO type should implement.
void SetStrategy();
}
public class SerialIO : IDataIO
{
public void SetStrategy()
{
//put the code that related to the Serial IO.
this.DataReceivedHandler += MyGuiUpdate;
this.DataReceivedHandler += MyDataProcessing;
}
}
public class TcpIO : IDataIO
{
public void SetStrategy()
{
//put the code that related to the Tcp IO.
//I will not implement it because it is a demo.
}
}
public class UdpIO : IDataIO
{
public void SetStrategy()
{
//put the code that related to the Udp IO.
//I will not implement it because it is a demo.
}
}
public class IO
{
IDataIO port = new IDataIO();
public void SetIOType(IDataIO ioType)
{
this.port = ioType;
port.SetStrategy();
}
}
public class IOManager
{
List<IO> ports = new List<IO>();
SerialIO serial = new SerialIO();
TcpIO tcp = new TcpIO();
ports[0].SetIOType(serial);
ports[1].SetIOType(tcp);
}
The interface IDataIO define basics that the all the IO types should implement.
The SerialIO, TcpIO, UdpIO classes derived from IDataIO implement the method SetStrategy() to meet each of their own need.
The IO class owns a field(named port) refers to a IDataIO type, this field can be setted to a certain IO type during the runtime by calling the method SetIOType() defined in the IO
class. Once this method is being called, we know which type the 'port' field refers to, and
then call the SetStrategy() method, it will run the overrided method in one of the IO class.
The IOManager class is the client. when it needs a certain IO type, say SerialIO, it only need to new a IO class and call the SetIOType() method by passing a SerialIO class instance, and all the logic related to the SerialIO type will be setted automatically.
Hope my description can help you.

Observer pattern with delegate and events using an event array

We have a class which manages many queues that store data. I want a user to get notified when new data is added to each of these queues. I'd like to use the observer pattern using delegate and events. Normally for a single event and source, we'd do:
public delegate void NewDataAddedDelegate();
public event NewDataAddedDelegate NewDataAdded;
and for the observer:
qManager.NewDataAdded += new qManager.NewDataAddedDelegate(getNewDataFunc);
But in this case, we have, say, 10 queues, each of which can receive data arbitrarily. So we'd like the observer functions to subscribe to an individual queue. We thought we could do:
public delegate void NewDataAddedDelegate();
public event NewDataAddedDelegate [] NewDataAdded; // can't do this
and in the constructor of qManager:
NewDataAdded = new NewDataAddedDelegate[numberOfQueues];
and in the observer:
qManager.NewDataAdded[0] += new qManager.NewDataAddedDelegate(getNewDataFunc0);
qManager.NewDataAdded[1] += new qManager.NewDataAddedDelegate(getNewDataFunc1);
but no go, since the event is expected to be a delegate type, not an array of delegates type.
Any ideas on how to approach this problem?
No, events don't work like that. Options:
Create another type which exposes the event, and have an array or collection of that type:
// Preferably *don't* just expose an array...
public TypeWithEvent[] Queues { get { ... } }
// Subscription:
qManager.Queues[i].NewDataAdded += ...
Alternatively, don't use events, and just have a method:
private NewDataAddededDelegate[] newDataAdded;
public void SubscribeNewDataAddedHandler(int queue,
NewDataAddedDelegate handler)
{
newDataAdded[queue] += handler;
}
// Subscription
qManager.SubscribeNewDataAddedHandler(0, ...);
Personally it sounds to me like each queue should really be its own object though... make the queue manager exposes a collection of queues, each of which can be subscribed to individually. (i.e. take the first approach.) Otherwise your queue manager is really doing too much work.
There are two approaches you might take there; the first is to have:
private NewDataAddedDelegate[] queues; // init not shown
public void Subscribe(int index, NewDataAddedDelegate handler) {
queues[index] += handler;
}
and use
obj.Subscribe(index, ...);
but you may want to think about synchronization etc around the subscription. A second approach is to create a wrapper class that has the event - then you can use the compiler's synchronization, which is good in C# 4.0:
public class SomeQueue {
public event NewDataAddedDelegate NewDataAdded;
}
and then expose those perhaps via an indexer, so you have
obj.Queues[index].NewDataAdded += ...
Personally, I expect the first is easier. It is only the synchronization that might be a nuisance. I do this in some pub-sub code, and IIRC I just lock during the subscribe.
You need to rethink this by actually applying the observer pattern rather that working on the basis of a fuzzy idea of a pattern.
Define your IObserver and ISubject interfaces and try to understand what's the observer and what are the subjects. In your case sounds like the queues are the subjects, not sure what the observers would be in your domain model.
Once you do this, things will be easier to figure out, and it's simply a matter of implementing the methods declared by your interfaces, for example your subjects (queues) will just call notify (and raise an event if you wanna use delegates) when something happens (item added to the queue).
Hope this helps.
Here is the working code in C#.
QueueManger exposes event NewDataAddedEvent which can be subscribed by one or more observers. Queue calls NewDataAdded() method on QueueManager on data change. QueueManager notifies if there are any subscribers with the parameter Queue. I hope this addresses your question.
using System;
using System.Collections.Generic;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
QueueManager queueManager = new QueueManager();
Observer observer = new Observer(queueManager);
Queue queue1 = queueManager.AddQueue();
Queue queue2 = queueManager.AddQueue();
queue1.OnNewDataAdd();
queue2.OnNewDataAdd();
Console.ReadLine();
}
delegate void NewDataAddedDelegate(Queue queue);
class Queue
{
QueueManager queueManager;
public string id;
public Queue(string id, QueueManager queueManager)
{
this.id = id;
this.queueManager = queueManager;
}
public void OnNewDataAdd()
{
this.queueManager.NewDataAdded(this);
}
}
class QueueManager
{
List<Queue> queues = new List<Queue>();
public Queue AddQueue()
{
Queue queue = new Queue((queues.Count + 1).ToString(), this);
this.queues.Add(queue);
return queue;
}
public event NewDataAddedDelegate NewDataAddedEvent;
public void NewDataAdded(Queue queue)
{
if (NewDataAddedEvent != null)
NewDataAddedEvent(queue);
}
}
class Observer
{
public Observer(QueueManager queueManager)
{
queueManager.NewDataAddedEvent += new NewDataAddedDelegate(queue_NewDataAdded);
}
void queue_NewDataAdded(Queue queue)
{
Console.WriteLine("Notification to the observer from queue {0}", queue.id);
}
}
}
}
Perhaps you could use the Event Aggregator pattern.
Not that you would have to code less, but it could create more clean/maintainable code.

Design pattern for handling multiple message types

I've got the GOF sitting on my desk here and I know there must be some kind of design pattern that solves the problem I'm having, but man I can't figure it out.
For simplicities sake, I've changed the name of some of the interfaces that I'm using.
So here's the problem, on one side of the wire, I've got multiple servers that send out different types of messages. On the other side of the wire I have a client that needs to be able to handle all the different types of messages.
All messages implement the same common interface IMessage. My problem is, when the client gets a new IMessage, how does it know what type of IMessage its received?
I supposed I could do something like the following, but this just FEELS awful.
TradeMessage tMessage = newMessage as TradeMessage;
if (tMessage != null)
{
ProcessTradeMessage(tMessage);
}
OrderMessage oMessage = newMessage as OrderMessage;
if (oMessage != null)
{
ProcessOrderMessage(oMessage);
}
The second thought, is to add a property to IMessage called MessageTypeID, but that would require me to write something like the following, which also FEELS awful.
TradeMessage tMessage = new TradeMessage();
if (newMessage.MessageTypeID == tMessage.MessageTypeID)
{
tMessage = newMessage as TradeMessage;
ProcessTradeMessage(tMessage);
}
OrderMessage oMessage = new OrderMessage();
if (newMessage.MessageTypeID == oMessage.MessageTypeID)
{
oMessage = newMessage as OrderMessage;
ProcessOrderMessage(oMessage);
}
I know this general problem has been tackled a million times, so there has to be a nicer way of solving the problem of having a method that takes an interface as a parameter, but needs different flow control based on what class has implemented that interface.
You could create separate message handlers for each message type, and naively pass the message to each available handler until you find one that can handle it. Similar to the chain of responsibility pattern:
public interface IMessageHandler {
bool HandleMessage( IMessage msg );
}
public class OrderMessageHandler : IMessageHandler {
bool HandleMessage( IMessage msg ) {
if ( !(msg is OrderMessage)) return false;
// Handle the message and return true to indicate it was handled
return true;
}
}
public class SomeOtherMessageHandler : IMessageHandler {
bool HandleMessage( IMessage msg ) {
if ( !(msg is SomeOtherMessage) ) return false;
// Handle the message and return true to indicate it was handled
return true;
}
}
... etc ...
public class MessageProcessor {
private List<IMessageHandler> handlers;
public MessageProcessor() {
handlers = new List<IMessageHandler>();
handlers.add(new SomeOtherMessageHandler());
handlers.add(new OrderMessageHandler());
}
public void ProcessMessage( IMessage msg ) {
bool messageWasHandled
foreach( IMessageHandler handler in handlers ) {
if ( handler.HandleMessage(msg) ) {
messageWasHandled = true;
break;
}
}
if ( !messageWasHandled ) {
// Do some default processing, throw error, whatever.
}
}
}
You could also implement this as a map, with the message class name or message type id as a key and the appropriate handler instance as the value.
Others have suggested having the message object "handle" itself, but that just doesn't feel right to me. Seems like it would be best to separate the handling of the message from the message itself.
Some other things I like about it:
You can inject the message handlers via spring or what-have-you rather than creating them in the constructor, making this very testable.
You can introduce topic-like behavior where you have multiple handlers for a single message by simply removing the "break" from the ProcessMessage loop.
By separating the message from the handler, you can have different handlers for the same message at different destinations (e.g. multiple MessageProcessor classes that handle the same messages differently)
A couple of solutions are applicable for this, first is best solution, last is least best. All examples are pseudocode:
1st, and best solution
Vincent Ramdhanie introduced the actual correct pattern to solve this problem, which is called the strategy pattern.
This pattern creates a separate 'processor', in this case to process the messages accordingly.
But I'm pretty sure a good explanation is given in your book by the GOF :)
2nd
As commented, the message may not be able to process itself, it is still usefull to create an interface for the message, or a base class, so you can make a general processing function for a message, and overload it for more specific ones.
overloading is in any case better then creating a different method for every type of message...
public class Message {}
public class TradeMessage extends Message {}
public class MessageProcessor {
public function process(Message msg) {
//logic
}
public function process(TradeMessage msg) {
//logic
}
}
3rd
If your message could process itself you could write an interface, since your process method depends on what message you got, it seems easier to put it inside the message class...
public interface IMessage
{
public function process(){}
}
you then implement this in all your message classes and proccess them:
list = List<IMessage>();
foreach (IMessage message in list) {
message.process();
}
in your list you can store any class that implements that interface...
From my experience with message handling, its usually the case that different consumers of messages require handling a variety of message types. I found the Double Dispatch pattern to handle this nicely. The basic idea is to register a set of handlers that dispatch the received messages to the handler for processing based on the specific type (using function overloading). The consumers only register for the specific types they wish to receive. Below is a class diagram.
The code looks like this:
IHandler
public interface IHandler
{
}
IMessageHandler
public interface IMessageHandler<MessageType> : IHandler
{
void ProcessMessage(MessageType message);
}
IMessage
public interface IMessage
{
void Dispatch(IHandler handler);
}
MessageBase
public class MessageBase<MessageType> : IMessage
where MessageType : class, IMessage
{
public void Dispatch(IHandler handler)
{
MessageType msg_as_msg_type = this as MessageType;
if (msg_as_msg_type != null)
{
DynamicDispatch(handler, msg_as_msg_type);
}
}
protected void DynamicDispatch(IHandler handler, MessageType self)
{
IMessageHandler<MessageType> handlerTarget =
handler as IMessageHandler<MessageType>;
if (handlerTarget != null)
{
handlerTarget.ProcessMessage(self);
}
}
}
DerivedMessageHandlerOne
// Consumer of DerivedMessageOne and DerivedMessageTwo
// (some task or process that wants to receive messages)
public class DerivedMessageHandlerOne :
IMessageHandler<DerivedMessageOne>,
IMessageHandler<DerivedMessageTwo>
// Just add handlers here to process incoming messages
{
public DerivedMessageHandlerOne() { }
#region IMessageHandler<MessaegType> Members
// ************ handle both messages *************** //
public void ProcessMessage(DerivedMessageOne message)
{
// Received Message one, do something with it
}
public void ProcessMessage(DerivedMessageTwo message)
{
// Received Message two, do something with it
}
#endregion
}
DerivedMessageOne
public class DerivedMessageOne : MessageBase<DerivedMessageOne>
{
public int MessageOneField;
public DerivedMessageOne() { }
}
Then you just have a container that manages the Handlers and you are all set. A simple for loop through the list of Handlers when a message received, and the Handlers receive the messages where they want them
// Receive some message and dispatch it to listeners
IMessage message_received = ...
foreach(IHandler handler in mListOfRegisteredHandlers)
{
message_received.Dispatch(handler);
}
This design came out of a question I asked awhile back about Polymorphic Event Handling
One option is to have the messages come with their own handlers. That is, create an Interface called IMessageProcessor that specifies a method processMessage(IMessage). Next define concrete class that implements IMessageProcessor for each type of message.
Each IMessage class will then define its own Processor.
When you receieve a message object you will do something like this:
message.processor.processMessage();
A dispatching pattern might work well.
public static class MessageDispatcher
{
private static readonly IMessageHandler s_DefaultHandler =
new DefaultMessageHandler();
private static readonly Dictionary<Type, IMessageHandler> s_Handlers =
new Dictionary<Type, IMessageHandler>();
static MessageDispatcher()
{
// Register a bunch of handlers.
s_Handlers.Add(typeof(OrderMessage), new OrderMessageHandler());
s_Handlers.Add(typeof(TradeMessage), new TradeMessageHandler());
}
public void Dispatch(IMessage msg)
{
Type key = msg.GetType();
if (s_Handlers.ContainsKey(key))
{
// We found a specific handler! :)
s_Handlers[key].Process(msg);
}
else
{
// We will have to resort to the default handler. :(
s_DefaultHandler.Process(msg);
}
}
}
public interface IMessageHandler
{
void Process(IMessage msg);
}
public class OrderMessageHandler : IMessageHandler
{
}
public class TradeMessageHandler : IMessageHandler
{
}
There are all kinds of variations to this theme. They will all have a dispatcher object that contains many different handlers. You should consider a default handler in case the dispatcher cannot find a specific handler. There is a lot of freedom in how you choose to dispatch the messages to the appropriate handlers. I just happen to dispatch based on type, but you could make it arbitrarily more complex. Maybe the dispatcher could examine the contents of the message to discover the best handler. Maybe the message carries with it a key that identifies a preferred handler. I don't know. There are a lot of possibilities here.
For my little messaging framework inside Silverlight app i'm using Mediator pattern. It's some kind of messaging bus/broker, to which objects are subscribing for specific type or types of message. Then this Mediator object (broker/bus) is deciding who will receive what kind of messages.
Someting like:
SubscribeFor<ChatMessage>().If(x=>x.SomeProp==true).Deliver(MyMethod);
Sample methods that are called:
void MyMethod(ChatMessage msg) , or
void MyMethod(BaseBessage msg)
or publishing (broadcasting) of messages:
Publish(new ChatMessage());
BaseMessage is abstract class, which all my messages inherits, and have just reference to sender and some unique Guid.
I took starting point for building my messaging framework from MVVM Light Toolkit, you can take a look at theirs source code, it's not complicated!
If you whish, I can put c# code for this somewhere?
Add a ProcessMessage() method to the iMessage interface and let the concrete message polymorphically decide the right way to process themselves.
Your code then becomes
newMessage.ProcessMessage();
Here is a good article on using polymorphism instead of conditionals.
You might want to take a look through Enterprise Integration Patterns by Gregor Hohpe and Bobby Woolf. It has a good catalog of patterns for message processing.
In a similar scenario I have a server which receives lots of different messages from multiple clients.
All messages are sent serialized and start with an identifier of message type. I then have a switch statement looking at the identifier. The messages are then deserialized (to very differing objects) and processed as appropriate.
A similar thing could be done by passing objects which implement an interface which includes a way of indicating message type.
public void ProcessMessage(IMessage msg)
{
switch(msg.GetMsgType()) // GetMsgType() is defined in IMessage
{
case MessageTypes.Order:
ProcessOrder(msg as OrderMessage); // Or some other processing of order message
break;
case MessageTypes.Trade:
ProcessTrade(msg as TradeMessage); // Or some other processing of trade message
break;
...
}
}
I know this is an older thread, with several very good answers over the years.
However, in 2018, I'd use a package such as Jimmy Bogard's MediatR (https://github.com/jbogard/MediatR).
It provides decoupling of message sending and processing with patterns such as request/response, Command/Query, One-way, Pub/Sub, async, polymorphic dispatching, etc.
I know it's super old, but I had to implement something similar today and I just wanted to mention some little useful sidenotes to the accepted answer,
first, to reduce code duplications (is X, is Y) in the concrete Handle implementation, I would recommend making an abstract handler class, so this:
public class OrderMessageHandler : IMessageHandler {
bool HandleMessage( IMessage msg ) {
if ( !(msg is OrderMessage)) return false;
// Handle the message and return true to indicate it was handled
return true;
}
}
public class SomeOtherMessageHandler : IMessageHandler {
bool HandleMessage( IMessage msg ) {
if ( !(msg is SomeOtherMessage) ) return false;
// Handle the message and return true to indicate it was handled
return true;
}
}
becomes:
public abstract class MessageHandler<T> : IMessageHandler where T : IMessage
{
bool HandleMessage(IMessage msg)
{
if (!(msg is T concreteMsg)) return false;
Handle(concreteMsg);
return true;
}
protected abstract void Handle(T msg);
}
public class OrderMessageHandler : MessageHandler<OrderMessage>
{
protected override void Handle(OrderMessage msg)
{
// do something with the concrete OrderMessage type
}
}
public class SomeOtherMessageHandler : MessageHandler<SomeOtherMessage>
{
protected override void Handle(SomeOtherMessage msg)
{
// do something with the concrete SomeOtherMessage type
}
}
and yea I would consider using Dictionary<Type, IMessageHandler> instead of foreach and forcing to return bool from handling to decide if it was handled , so my final answer would be:
*(ConcreteType is not a must, it's there to help you to add the handler without specifying the type)
public interface IMessageHandler
{
Type ConcreteType { get; }
void HandleMessage(IMessage msg);
}
public abstract class MessageHandlerBase<TConcreteMessage> : IMessageHandler where TConcreteMessage : IMessage
{
public Type ConcreteType => typeof(TConcreteMessage);
public void HandleMessage(IMessage msg)
{
if (msg is not TConcreteMessage concreteMsg) return;
Handle(concreteMsg);
}
protected abstract void Handle(TConcreteMessage msg);
}
public class OrderMessageHandler : MessageHandlerBase<OrderMessage>
{
protected override void Handle(OrderMessage msg)
{
// do something with the concrete OrderMessage type
}
}
public class SomeOtherMessageHandler : MessageHandlerBase<SomeOtherMessage>
{
protected override void Handle(SomeOtherMessage msg)
{
// do something with the concrete SomeOtherMessage type
}
}
public class MessageProcessor
{
private readonly Dictionary<Type, IMessageHandler> _handlers = new();
public MessageProcessor()
{
}
public void AddHandler(IMessageHandler handler)
{
var concreteMessageType = handler.ConcreteType;
if (_handlers.ContainsKey(concreteMessageType))
{
throw new Exception($"handler for type {concreteMessageType} already exists.");
//if you want to support multiple handlers for same type it can be solved with dictionary of List<T>
}
_handlers[concreteMessageType] = handler;
}
public void ProcessMessage(IMessage msg)
{
if (_handlers.TryGetValue(msg.GetType(), out var handler))
{
handler.HandleMessage(msg);
}
else
{
// Do some default processing, throw error, whatever.
}
}
}
public class OrderMessage : IMessage
{
public Guid Guid { get; set; }
public int Number { get; set; }
}
public class SomeOtherMessage : IMessage
{
public Guid Guid { get; set; }
public string Text { get; set; }
}
Hope it can help someone in the future :)

Categories