A better pattern for handling specific objects sharing the same interface?

Hi there /r/csharp. I'll jump straight in. Here's a properly formatted gist of the code below.

Suppose I have an IMessageHandler which handles a specific message sent from somewhere down the wire:

public interface IMessageHandler { void HandleMessage(IMessage message); } public interface IMessage { MessageIdentifier MessageIdentifier { get; } } public enum MessageIdentifier { ClientDisconnection, LoginRequest } 

Messages are used to pass around information, stripped away, they look like so:

public class LoginRequest : IMessage { public MessageIdentifier MessageIdentifier => MessageIdentifier.LoginRequest; } public class ClientDisconnection : IMessage { public MessageIdentifier MessageIdentifier => MessageIdentifier.ClientDisconnection; } 

And a Generic Abstract MessageHandler implementation which handles specific messages:

public abstract class MessageHandler<TMessage> : IMessageHandler where TMessage : IMessage { public void HandleMessage(IMessage message) { HandleMessage((TMessage) message); } public abstract void HandleMessage(TMessage message); } public class ClientDisconnectionHandler : MessageHandler<ClientDisconnection> { public override void HandleMessage(ClientDisconnection message) { throw new System.NotImplementedException(); } } public class LoginRequestHandler : MessageHandler<LoginRequest> { public override void HandleMessage(LoginRequest message) { throw new System.NotImplementedException(); } } 

And a MessageHandlerRegistry defines what MessageHandler to use for the incoming Message's MessageIdentifier

public static class MessageHandlerRegistry { public static readonly Dictionary<MessageIdentifier, IMessageHandler> MessageHandlersIndexedByMessageIdentifier = new Dictionary<MessageIdentifier, IMessageHandler> { {MessageIdentifier.ClientDisconnection, new ClientDisconnectionHandler()}, {MessageIdentifier.LoginRequest, new LoginRequestHandler()} }; } 

Finally, this is used by a service like so:

IMessageHandler handler = MessageHandlerRegistry.MessageHandlersIndexedByMessageIdentifier[message.MessageIdentifier]; handler.HandleMessage(message); 

I have a few questions:

  • Is there any other pattern which can be used to circumvent having a registry (or lookup). Furthermore, remove the need of having a MessageIdentifier for each IMessage?

  • Does the MessageHandler<TMessage> pattern (where a non-abstract method is used to cast the object ready for the abstract method to use) have a name? Is there a way I can avoid this clutter and just create a MessageHandler<TMessage> without an IMessageHandler interface? It seems like I need the IMessageHandler interface in order to use a message handler registry.

TL;DR: Enlighten me on how I can improve a design where types and their handlers are defined in a dictionary.

by JypJyp via /r/csharp

Leave a Reply