Reusable non generic method for generic methods - c#

I have the following base interface
public interface IHandler{
void Handle(IMessage message);
}
and an generic interface inheriting the base interface
public interface IHandler<TMessage> : IHandler where TMessage : IMessage{
void Handle(TMessage message);
}
My classes can implement the interface IHandler<TMessage> mutiple times. IMessage is an base interface for messages and isn´t relevant here. Currently i´m implementing the interfaces as follows.
public class ExampleHandler : IHandler<ExampleMessage>, IHandler<OtherExampleMessag>{
void IHandler.Handle(IMessage message){
ExampleMessage example = message as ExampleMessage;
if (example != null) {
Handle(example);
}
else {
OtherExampleMessage otherExample = message as OtherExampleMessage;
if (otherExample != null) {
Handle(otherExample);
}
}
public void Handle(ExampleMessage) {
//handle message;
}
public void Handle(OtherExampleMessage) {
//handle message;
}
}
What bothers me is the way i have to implement the Handle(IMessage) method, cause in my opinion its many redundant code, and i have to extend the method each time when i implement a new IHandler<TMessage> interface on my class.
What i´m looking for is a more generic way to implement the Handle(IMessage) method (maybe in a base class for Handlers), but i´m currently stuck how to do that.

You can use the new dynamic keyword to move the overload resolution to the DLR:
void IHandler.Handle(IMessage message)
{
dynamic d = message;
Handle(d);
}
Please note that this will fail at runtime with a RuntimeBinderException if the message passed in is not valid for your class.
To avoid this exception you can add a Handler for all unknown message types:
private void Handle(object unknownMessage)
{
// Handle unknown message types here.
}
To implement IHandler.Handle in a base class, you need to do a little bit more work:
public class BaseHandler : IHandler
{
void IHandler.Handle(IMessage message)
{
dynamic d = message;
Handle(d);
}
private void Handle<TMessage>(TMessage message) where TMessage : IMessage
{
var handler = this as IHandler<TMessage>;
if(handler == null)
HandleUnknownMessage(message);
else
handler.Handle(message);
}
protected virtual void HandleUnknownMessage(IMessage unknownMessage)
{
// Handle unknown message types here.
}
}
Your specific handler would than look like this:
public class ExampleHandler : BaseHandler,
IHandler<ExampleMessage>,
IHandler<OtherExampleMessage>
{
public void Handle(ExampleMessage message)
{
// handle ExampleMessage here
}
public void Handle(OtherExampleMessage message)
{
// handle OtherExampleMessage here
}
}
This code now works like this:
The DLR calls the generic BaseHandler.Handle<TMessage> method with the real message type, i.e. TMessage will not be IMessage but the concrete message class like ExampleMessage.
In this geneirc handler method, the base class tries to case itself to a handler for the specific message.
If that is not successful, it calls HandleUnknownMessage to handle the unknown message type.
If the cast is successful, it calls the Handle method on the specific message handler, effectifly delegating the call to the concrete Handler implementation.

A reasonable way would be some judicious use of reflection:
var method = this.GetType().GetMethod("Handle", new[] { message.GetType() });
if (method != null) {
method.Invoke(this, new[] { message });
}
If you are doing this so much that performance is a problem you could cache the results of the test for a massive improvement.

You stuck because your class (in the question) does more than one thing. It deals with ExampleMessage and OtherExampleMessage. I suggest you create one class to handle one thing.
Example:
public class ExampleHandler : IHandler<ExampleMessage>
and
public class OtherExampleHandler : IHandler<OtherExampleMessag>
From my understanding, you want to have a class to handle some kind of events. In this case, you may have to use Observer pattern to notify each Handler when something happen and let they do their work.

The interfaces are saying that you have an instance that provides N services. Sure the services are similar but as they are for different types they are independent services. So your detecting a 'code smell'. The smell is 'why a common method for different services?'.
So are the services different enough to justify the generic interface declarations? The fundamental here is 'duplication'. Refactor out the duplication. Duplication is BAD. Once you move the duplicate stuff out then the answer will be self evident.
To put this another way, get rid of the common method and handle each in its own method ... the duplication is what you want to move out to another class. If so, think injection.
Love your smell detection!

Related

foreach loop can not cast type to the interface it implements

Edited with complete, working, code-example.
In my IRC app, the application receives content from an IRC server. The content is sent in to a factory and the factory spits out an IMessage object that can be consumed by the presentation layer of the application. The IMessage interface and a single implementation is shown below.
public interface IMessage
{
object GetContent();
}
public interface IMessage<out TContent> : IMessage where TContent : class
{
TContent Content { get; }
}
public class ServerMessage : IMessage<string>
{
public ServerMessage(string content)
{
this.Content = content;
}
public string Content { get; private set; }
public object GetContent()
{
return this.Content;
}
}
To receive the IMessage object, the presentation layer subscribes to notifications that are published within my domain layer. The notification system iterates over a collection of subscribers to a specified IMessage implementation and fires a callback method to the subscriber.
public interface ISubscription
{
void Unsubscribe();
}
public interface INotification<TMessageType> : ISubscription where TMessageType : class, IMessage
{
void Register(Action<TMessageType, ISubscription> callback);
void ProcessMessage(TMessageType message);
}
internal class Notification<TMessage> : INotification<TMessage> where TMessage : class, IMessage
{
private Action<TMessage, ISubscription> callback;
public void Register(Action<TMessage, ISubscription> callbackMethod)
{
this.callback = callbackMethod;
}
public void Unsubscribe()
{
this.callback = null;
}
public void ProcessMessage(TMessage message)
{
this.callback(message, this);
}
}
public class NotificationManager
{
private ConcurrentDictionary<Type, List<ISubscription>> listeners =
new ConcurrentDictionary<Type, List<ISubscription>>();
public ISubscription Subscribe<TMessageType>(Action<TMessageType, ISubscription> callback) where TMessageType : class, IMessage
{
Type messageType = typeof(TMessageType);
// Create our key if it doesn't exist along with an empty collection as the value.
if (!listeners.ContainsKey(messageType))
{
listeners.TryAdd(messageType, new List<ISubscription>());
}
// Add our notification to our listener collection so we can publish to it later, then return it.
var handler = new Notification<TMessageType>();
handler.Register(callback);
List<ISubscription> subscribers = listeners[messageType];
lock (subscribers)
{
subscribers.Add(handler);
}
return handler;
}
public void Publish<T>(T message) where T : class, IMessage
{
Type messageType = message.GetType();
if (!listeners.ContainsKey(messageType))
{
return;
}
// Exception is thrown here due to variance issues.
foreach (INotification<T> handler in listeners[messageType])
{
handler.ProcessMessage(message);
}
}
}
In order to demonstrate how the above code works, I have a simple Console application that subscribes to notifications from the above ServerMessage type. The console app first publishes by passing the ServerMessage object in to the Publish<T> method directly. This works without any issues.
The 2nd example has the app creating an IMessage instance using a factory method. The IMessage instance is then passed in to the Publish<T> method, causing my variance issue to throw an InvalidCastException.
class Program
{
static void Main(string[] args)
{
var notificationManager = new NotificationManager();
ISubscription subscription = notificationManager.Subscribe<ServerMessage>(
(message, sub) => Console.WriteLine(message.Content));
notificationManager.Publish(new ServerMessage("This works"));
IMessage newMessage = MessageFactoryMethod("This throws exception");
notificationManager.Publish(newMessage);
Console.ReadKey();
}
private static IMessage MessageFactoryMethod(string content)
{
return new ServerMessage(content);
}
}
The exception states that I can not cast an INotification<IMessage> (what the Publish method is understands the message being published to be) in to an INotification<ServerMessage>.
I have tried to mark the INotification interface generic as contravariant, like INotification<in TMessageType> but can't do that because I'm consuming TMessageType as a parameter to the Register method's callbacks. Should I split the interface in to two separate interfaces? One that can register and one that can consume? Is that the best alternative?
Any additional help on this would be great.
The basic issue here is that you are trying to use your types in a variant way, but that's not supported for the syntax you are trying to use. Thanks to your updated and now complete (and nearly minimal) code example, it's also clear that you simply can't do this the way you have it written now.
The interface in question, and in particular the method you want to use (i.e. ProcessMessage(), could in fact be declared as a covariant interface (if you split the Register() method into a separate interface). But doing so would not solve your problem.
You see, the issue is that you are trying to assign an implementation of INotification<ServerMessage> to a variable typed as INotification<IMessage>. Note that once that implementation is assigned to the variable of that type, the caller could pass any instance of IMessage to the method, even one that is not an instance of ServerMessage. But the actual implementation expects (nay, demands!) an instance of ServerMessage.
In other words, the code you are trying to write simply is not statically safe. It has no way at compile time to guarantee that the types match, and that's just not something C# is willing to do.
One option would be to weaken the type-safety of the interface, by making it non-generic. I.e. just have it always accept an IMessage instance. Then each implementation would have to cast according to its needs. Coding errors would be caught only at run-time, with an InvalidCastException, but correct code would run fine.
Another option would be to set the situation up so that the full type parameter is known. For example, make PushMessage() generic method too, so that it can call Publish() using the type parameter of ServerMessage instead of IMessage:
private void OnMessageProcessed(IrcMessage message, IrcCommand command, ICommandFormatter response)
{
this.OnMessageProcessed(message);
ServerMessage formattedMessage = (ServerMessage)response.FormatMessage(message, command);
this.PushMessage(formattedMessage);
}
private void PushMessage<T>(T notification) where T : IMessage
{
this.notificationManager.Publish(notification);
}
That way, the type parameter T would match exactly in the foreach loop where you're having the problem.
Personally, I prefer the second approach. I realize that in your current implementation, this doesn't work. But IMHO it could be worth revisiting the broader design to see if you can accomplish the same feature while preserving the generic type throughout, so that it can be used to ensure compile-time type safety.
Long stretch here, from fiddling around with the code you provided...
Using breakpoints, may I know what the method thinks T is and what the type of listeners[messageType] is?
foreach (Notification<T> handler in listeners[messageType])
{
handler.ProcessMessage(message);
}
Because if indeed it's Notification<IMessage> on one side and Notification<ServerMessage> on the other, then yes this is an assignment compatibility issue.
There's a solution, but you have not shown code for how Notification is built. I'll extrapolate from your current code base. This should be all you need.
public interface INotification<in T> { /* interfacy stuff */ }
public class Notification<T>: INotification<T> { /* classy stuff */ }
Then modify the code in such a way that essentially this is called:
foreach (INotification<T> handler in listeners[messageType]) { /* loop stuff */ }
Where listeners[messageType] must be INotification.
This should prevent the need to cast your Notification to Notification explicitly like the compiler is complaining.
The magic occurs in the interface declaration for INotification, the in T key phrase (bad terminology, sorry), lets the compiler know that T is contravariant (by default, if you omit out, T is invariant, as in types must match).
EDIT: Per the comments, I have updated the answer to reflect the code that's actually written as opposed to what I thought was written. This mainly means declaring INotification as contravariant (in T) as opposed to covariant (out T).
I solved this by adding another level of indirection. Having followed advice from #PeterDuniho, I broke apart the INotification<TMessage> interface in to two separate interfaces. By adding the new INotificationProcessor interface, I can change my collection of listeners from an ISubscription to an INotificationProcessor and then iterate over my collection of listeners as an INotificationProcessor.
public interface ISubscription
{
void Unsubscribe();
}
public interface INotification<TMessageType> : ISubscription where TMessageType : class, IMessage
{
void Register(Action<TMessageType, ISubscription> callback);
}
public interface INotificationProcessor
{
void ProcessMessage(IMessage message);
}
The INotificationProcessor implementation, implements both INotificationProcessor and INotification<TMessageType>. This allows the Notification class below to cast the IMessage provided in to the appropriate generic type for publication.
internal class Notification<TMessage> : INotificationProcessor, INotification<TMessage> where TMessage : class, IMessage
{
private Action<TMessage, ISubscription> callback;
public void Register(Action<TMessage, ISubscription> callbackMethod)
{
this.callback = callbackMethod;
}
public void Unsubscribe()
{
this.callback = null;
}
public void ProcessMessage(IMessage message)
{
// I can now cast my IMessage to T internally. This lets
// subscribers use this and not worry about handling the cast themselves.
this.callback(message as TMessage, this);
}
}
My NotificationManager can now hold a collection of INotificationProcessor types instead of ISubscription and invoke the ProcessMessage(IMessage) method regardless if what comes in to it is an IMessage or a ServerMessage.
public class NotificationManager
{
private ConcurrentDictionary<Type, List<INotificationProcessor>> listeners =
new ConcurrentDictionary<Type, List<INotificationProcessor>>();
public ISubscription Subscribe<TMessageType>(Action<TMessageType, ISubscription> callback) where TMessageType : class, IMessage
{
Type messageType = typeof(TMessageType);
// Create our key if it doesn't exist along with an empty collection as the value.
if (!listeners.ContainsKey(messageType))
{
listeners.TryAdd(messageType, new List<INotificationProcessor>());
}
// Add our notification to our listener collection so we can publish to it later, then return it.
var handler = new Notification<TMessageType>();
handler.Register(callback);
List<INotificationProcessor> subscribers = listeners[messageType];
lock (subscribers)
{
subscribers.Add(handler);
}
return handler;
}
public void Publish<T>(T message) where T : class, IMessage
{
Type messageType = message.GetType();
if (!listeners.ContainsKey(messageType))
{
return;
}
// Exception is thrown here due to variance issues.
foreach (INotificationProcessor handler in listeners[messageType])
{
handler.ProcessMessage(message);
}
}
}
The original app example now works without issue.
class Program
{
static void Main(string[] args)
{
var notificationManager = new NotificationManager();
ISubscription subscription = notificationManager.Subscribe<ServerMessage>(
(message, sub) => Console.WriteLine(message.Content));
notificationManager.Publish(new ServerMessage("This works"));
IMessage newMessage = MessageFactoryMethod("This works without issue.");
notificationManager.Publish(newMessage);
Console.ReadKey();
}
private static IMessage MessageFactoryMethod(string content)
{
return new ServerMessage(content);
}
}
Thanks everyone for the help.

How to dynamically invoke delegates with known parameter base type?

I am trying to implement my own messaging system for a Unity game. I have a basic version working - a very simplified example of this is as follows:
// Messaging class:
private Dictionary<Type, List<Func<Message, bool>>> listeners; // Set up by some other code.
public void AddListener<T>(Func<Message, bool> listener) where T : Message {
this.listeners[typeof(T)].Add(listener);
}
public void SendMessage<T>(T message) where T : Message {
foreach (Func<Message, bool> listener in this.listeners[typeof(T)]) {
listener(message);
}
}
// Some other class:
private void Start() {
messaging.AddListener<MyMessage>(this.MessageHandler); // Subscribe to messages of a certain type.
}
private bool MessageHandler(Message message) { // We receive the message as the Message base type...
MyMessage message2 = (MyMessage)message; // ...so we have to cast it to MyMessage.
// Handle the message.
}
This all works fine. What I would like to do now is implement some "magic" to allow the message handler to be called with the actual derived type, like this:
private bool MessageHandler(MyMessage message) {
// Handle the message.
}
This would mean that the message handling code across thousands of scripts will not need to bother casting the Message object to the correct derived type - it will already be of that type. It would be far more convenient. I feel like this could be possible to achieve somehow using generics, delegates, expression trees, covariance and/or contravariance, but I'm just not getting it!
I've been trying a lot of different things, and feel like I am getting close, but I just can't get there. These are the two partial solutions that I've been able to come up with:
// Messaging class:
private Dictionary<Type, List<Delegate>> listeners; // Delegate instead of Func<Message, bool>.
public void AddListener<T>(Func<T, bool> listener) where T : Message { // Func<T, bool> instead of Func<Message, bool>.
this.listeners[typeof(T)].Add(listener);
}
public void SendMessage<T>(T message) where T : Message {
foreach (Delegate listener in this.listeners[typeof(T)]) {
listener.Method.Invoke(method.Target, new object[] { message }); // Partial solution 1.
((Func<T, bool>)listener)(message); // Partial solution 2.
}
}
Partial solution 1 works fine, but it uses reflection, which isn't really an option considering the performance - this is a game, and the messaging system will be used a lot. Partial solution 2 works, but only as long as the T generic parameter is available. The messaging system will also have a queue of Message objects that it will process, and T will not be available there.
Is there any way to achieve this? I would greatly appreciate any help that anyone could offer!
One final thing to note is that I am using Unity, which uses Mono - .NET 4 is not an option, and as far as I know this rules out using "dynamic".
If I understood your question correctly, you want to have some common way of storing and invoking message handlers while providing a specific message type to each handler.
One way to do it is to use base-typed inteface handler and generic-typed implementation:
interface IMessageHandler
{
bool ProcessMessage(Message m);
}
class MessageHandler<T>: IMessageHandler where T:Message
{
Func<T, bool> handlerDelegate;
public MessageHandler(Func<T, bool> handlerDelegate)
{
this.handlerDelegate = handlerDelegate;
}
public bool ProcessMessage(Message m)
{
handlerDelegate((T)m);
}
}
Your handler dictionary should hold IMessageHandler as a value, and in your AddListener method create a MessageHandler and add it to handler dictionary. Like this:
private Dictionary<Type, IMessageHandler> listeners;
public void AddListener<T>(Func<T, bool> listener) where T : Message
{
this.listeners[typeof(T)].Add(new MessageHandler<T>(listener));
}
public void SendMessage(Message message)
{
foreach (IMessageHandler listener in this.listeners[message.GetType()])
{
listener.ProcessMessage(message);
}
}
That way you can call SendMessage without generic parameter and get typed argument in your actual handler method.
Basically you get stuck on the fact that Func<Base, bool> cannot point to bool Method(Derived d). So there's no safe type for storing handles to listeners.
I think one way might be to forgo the common Dictionary of listeners and make the container class generic. So then you'd have message pumps (or atleast containers) for every type. Ex. Something like this?
abstract class BaseMessagePump
{
protected abstract void SendMessage(Message m);
public void AddListener<T>(Func<T, bool> l) where T : Message
{
//check a dictionary / cache
new GenericMessageQueue<T>().listeners.Add(l);
}
}
class GenericMessageQueue<T> : BaseMessagePump where T : Message
{
public List<Func<T, bool>> listeners;
protected override void SendMessage(Message m)
{
listeners[0]((T)m);//the cast here is safe if you do correct cache / type checking in the base add listener
}
}

Do I need type checking for a C# object factory to call the appropriate methods?

Given the following pseudo C# code:
class BigMessage : Message { }
class SmallMessage : Message { }
abstract class Message
{
static public Message Factory()
{
Random random = new Random();
int randomNumber = random.Next(0, 100);
if (randomNumber > 50)
{
return new BigMessage();
}
else
{
return new SmallMessage();
}
}
}
class Worker
{
public void Comprehend(BigMessage bm)
{
}
public void Comprehend(SmallMessage bm)
{
}
public void start() {
Message msg = Message.Factory();
Comprehend(msg);
}
}
If I ask the Factory to give me a random Message object inherited from Message (e.g. Big or Small Message), and I would like the Comprehend methods in the Worker class to act on the type of message given using overloading (the proper OO way, rather than explicit type checking), why do I get the following two types of errors and can you help me understand what I am doing wrong?
The best overloaded method match for 'Worker.Comprehend(BigMessage)' has some invalid arguments.
cannot convert from 'Message' to 'BigMessage'
Ultimately I expect the Factory to provide me with an object inherited from Message, who's type I do not know in advance. I do need to act differently given the different type returned. Inheritance is very helpful in this scenario as the abstract class provides much useful functionality shared with it's child classes.
.NET 4.5 is used.
Thanks in advance!
The reason that you get the conversion error is that you cannot convert a "Message" type to a concrete "BigMessage" or "SmallMessage". It should be the other way around where you have Comprehend(Message msg) and that allows the method to accept any inherited objects.
In addition, what I think you are trying to achieve is polymorphism. I believe to correctly create your objects, your base abstract class Message should have a method called "Comprehend" and in your worker process, you call msg.Comprenhend(). This way, as you get more additional message types, you are not adding additional comprehend methods to your worker class for each message. By leveraging OOP and inheritance, you let the object decide how they comprehend themselves.
sample code below:
abstract class Message
{
abstract void Comprehend();
public static Message Factory(){... code here to return message }
}
class BigMessage : Message
{
public void Comprehend()
{
//do work here
}
}
class SmallMessage : Message
{
public void Comprehend()
{
//do work here
}
class Worker
{
public void Start()
{
var msg = Message.Factory();
msg.Comprehend();
}
}
Hope this helps!

Generic Interfaces and Type Parsing

I am trying to pass messages between several classes that communicate through interface. However, as I like to go as generic as possible, I ran into problems because the message type of incoming messages may be different from the outgoing type. I pasted some code to make it clearer.
The code below does not compile because the interface implementation passes a different type than the type of the blocking collection to which it is supposed to add incoming messages. I want to be able to send types potentially different from incoming types (incoming types obviously always match the type of the elements in the blocking collection). Can I somehow get around any sort of casting or parsing even if that means I need to redesign my interface or class?
I am still quite fresh when it comes to working with interfaces and struggled with recursions, stack overflow errors, and the like. So, if you have suggestions what I can improve design wise or just a quick fix then please help me to learn. Am very eager to understand how to implement a better pattern.
Thanks
public interface IClientMessaging
{
void MessagePassing<U>(U message);
}
public class InProcessMessaging<T> : IClientMessaging
{
private Dictionary<Type, List<IClientMessaging>> Subscriptions;
public BlockingCollection<T> MessageBuffer;
public InProcessMessaging(Dictionary<Type, List<IClientMessaging>> subscriptions)
{
//Setup Message Buffer
MessageBuffer = new BlockingCollection<T>();
//Subscribe
Type type = typeof(T);
if (subscriptions.Keys.Contains(type))
{
subscriptions[type].Add(this);
}
else
{
subscriptions.Add(type, new List<IClientMessaging>());
subscriptions[type].Add(this);
}
Subscriptions = subscriptions;
}
public void SendMessage<U>(U message)
{
//Send message to each subscribed Client
List<IClientMessaging> typeSubscriptions = Subscriptions[typeof(U)];
foreach (IClientMessaging subscriber in typeSubscriptions)
{
subscriber.MessagePassing<U>(message);
}
}
public T ReceiveMessage()
{
return MessageBuffer.Take();
}
public bool ReceiveMessage(out T item)
{
return MessageBuffer.TryTake(out item);
}
//Interface Implementation
public void MessagePassing<U>(U message)
{
MessageBuffer.Add(message); //<-"Cannot convert from U to T" [this is because I want
//to send messages of a different type than the receiving type]
}
}
I'm struggling to understand your goal here, but perhaps MessagePassing<U>(U message) should be MessagePassing(U message) and interface IClientMessaging should be interface IClientMessaging<U>.
Then InProcessMessaging<T, U> : IClientMessaging<U> - but I don't see why InProcessMessaging implements IClientMessaging AND manages subscriber lists of IClientMessaging. Seems to me that one class would manage the subscribers and another IS a subscriber (IClientMessaging).
You say U and T are different types. Well - are they related? Is one wrapper for the other? Sounds like maybe U is either a wrapper for T, a generic class itself that contains the T but adds extra info. In that case, void MessagePassing<T>(Wrapper<T> message);
UPDATES
Based on the comments so far ...
interface IClientMessage {}
interface IClientMessage<U> : IClientMessage { /* ... */ }
But rename those to:
interface IConsumer {} // (Or ISubscriber?)
interface IConsumer<TConsumed> : IConsumer{ /* ... */ }
and add:
interface IGenerator { }
interface IGenerator <TGenerated> : IGenerator {
event EventHandler<TGenerated> ItemGenerated;
}
Then:
class Manager
{
Dictionary<TConsumed, IConsumer> consumers = new ...
/* Code for attaching ItemGenerated event handlers to clients */
}
class MyClient : IGenerator<string>, IConsumer<Foo>, IConsumer<Bar>
{
event IGenerator<string>.ItemGenerated ...
void IConsumer<Foo>.Consume(...) ...
void IConsumer<Bar>.Consume(...) ...
}
Yes, this would use reflection to invoke IConsumer<TConsumed>.Consume(). Or you can leave off the generics and just use object as your types. Better yet, IClientMessage can have a Consume(object message) which in your implementation can ensure that object is a TConsumed before attempting to process it.
You could otherwise create direct client-to-client links through C# events, but you seem intent on a central dispatcher. It is the central dispatchers need to keep track of these different and unbounded number of types that is either going to require reflection OR be unaware of the types being passed (as described in the previous paragraph)
You should look at Reactive Extensions and the Observer pattern for ideas as well.
I removed my comments because it was getting too chatty.

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