I have (non-polymorphic) messages, which I want to handle according to their MessageType field. It is close to the command-pattern discussed here (and which I have working with tests):
- Castle Windsor & Command Pattern
- Windsor registration for generic commands/command handlers
- http://kozmic.net/2010/03/11/advanced-castle-windsor-ndash-generic-typed-factories-auto-release-and-more/
Execpt, I don't have separate classes or generic types for each MessageType. I would prefer not to have to introduce such types (legacy reasons).
Roughly like:
public interface IMessage {
int MessageType { get; }
IList<byte> Payload { get; }
}
class Message: IMessage {
// Implementation
}
public interface IHandler {
void Handle(IMessage message);
}
public abstract class TypedMessageHandler: IHandler {
public abstract int RequiredMessageType { get; }
public virtual void Handle(IMessage message) {
if (message.CommandType != RequiredMessageType)
throw new ArgumentException(nameof(message)) // More info :)
InnerHandle(message);
}
protected abstact void InnerHandle(IMessage message);
}
class MessageType0Handler: TypedMessageHandler {
public int RequiredMessageType => 0;
override void InnerHandle(IMessage message) => // Do stuff;
}
class MessageType1Handler: TypedMessageHandler {
public int RequiredMessageType => 1;
override void InnerHandle(IMessage message) => // Do stuff;
}
// Some registration that I can use to dispatch from `msg: IMessage` to
// `IHandler` with `RequiredMessageType == msg.MessageType`.
How can I do this dispatch with Windsor? Preferably with some registrations based on queries on the defined types.
The trick with a TypedFactory from the above articles is not immediately useful.
I've been playing with tagging the handlers with custom attributes, but I can't figure out how to both:
- Get the command argument (IMessage instance), and
- use a custom IHandlerSelector to filter the IHandler implementations based on such an attribute.
I would recommend to add
RequiredMessageTypeto yourIHandlerinterface:Than you can create your own Dispatcher:
And Castle registration would be something like: