I wrote a message switching library with a similar scenario a while back, and I decided to use generics to pass the user-defined enum. The main problem with this is you can't constrain your generic to only enum types, but can only say while T: struct. Someone may instantiate your type with some other primitive type (although, using ints could still be functional, provided they're all unique values. The dictionary will throw an exception if they're not. You could possibly add some additional check using reflection to ensure you pass an enum.
public abstract class DefaultMessageHandler<T> : IMessageHandler<T> where T : struct {
public delegate void MessageHandlerDelegate(IMessage<T> message, IConnection connnection);
private readonly IDictionary<T, MessageHandlerDelegate> messageHandlerDictionary =
new Dictionary<T, MessageHandlerDelegate>();
protected void RegisterMessageHandler(T messageType, MessageHandlerDelegate handler) {
if (this.messageHandlerDictionary.ContainsKey(messageType))
return;
else this.messageHandlerDictionary.Add(messageType, handler);
}
protected void UnregisterMessageHandler(T messageType) {
if (this.messageHandlerDictionary.ContainsKey(messageType))
this.messageHandlerDictionary.Remove(messageType);
}
protected virtual void HandleUnregisteredMessage(IMessage<T> message, IConnection connection) {
}
void IMessageHandler<T>.HandleMessage(IMessage<T> message, IConnection connection) {
if (this.messageHandlerDictionary.ContainsKey(message.MessageType))
this.messageHandlerDictionary[message.MessageType].Invoke(message, connection);
else HandleUnregisteredMessage(message, connection);
}
}
Given your example scenario, you'd just subclass it like this.
public sealed class ServerOperationHandler : DefaultMessageHandler<ServerOperationCode> {
public ServerOperationHandler() {
this.RegisterMessageHandler(ServerOperationCode.LoginResponse, this.HandleLoginResponse);
this.RegisterMessageHandler(ServerOperationCode.SelectionResponse, this.HandleSelectionResponse);
}
private void HandleLoginResponse(IMessage<ServerOperationCode> message, IConnection connection) {
//TODO
}
private void HandleSelectionResponse(IMessage<ServerOperationCode> message, IConnection connection) {
//TODO
}
}