I have an architecture like the one described in this blog post. In summary, I have command objects, e.g. :
public class MoveCustomerCommand : ICommand
{
public int CustomerId { get; set; }
public Address NewAddress { get; set; }
}
And command handlers for each command which derive from the interface ICommandHandler<TCommand>:
public interface ICommandHandler<TCommand> where TCommand : ICommand
{
void Handle(TCommand command);
}
public class MoveCustomerCommandHandler : ICommandHandler<MoveCustomerCommand>
{
public void Handle(MoveCustomerCommand command)
{
// Logic here
}
}
Now I'm looking for a clean solution to the following use case: Some clients produce a batch of heterogenous commands that need to be processed. In other words, I want to implement the following:
void HandleBatch(List<ICommand> batch) {
}
I have some ideas but I'm not convinced that any of them is good enough.
Option 1 Put a humongous switch-case in the HandleBatch function.
void HandleBatch(List<ICommand> batch) {
foreach (var command in batch) {
switch (command) {
case MoveCustomerCommand cmd:
new MoveCustomerCommandHandler().Handle(cmd);
break;
case DeleteCustomerCommand cmd:
new DeleteCustomerCommandHandler().Handle(cmd);
break;
// ....
}
}
}
Option 2 Use reflections to find the appropriate command handler for each command.
void HandleBatch(List<ICommand> batch) {
foreach (var command in batch) {
var commandType = command.GetType();
var handlerInterface = typeof(ICommandHandler<>)
.MakeGenericType(new Type[]{commandType});
// Search the current assembly for a type that implements "handlerInterface"
var handlerType = Assembly.GetAssembly(this.GetType())
.GetTypes()
.Where(t => t != handlerInterface &&
handlerInterface.IsAssignableFrom(t)
).First();
var handler = CreateInstance(handlerType);
handler.Handle(command);
}
}
Option 3 Same as option 2, but also annotate all the Handlers with a custom annotation and when searching for the type filter by annotation as well.
Option 4 Something else?
Another inconvenience is that the HandleBatch will have to have handy an instance of virtually every possible dependency since most of the logic of the application is in these commands. But I guess I can't go around this.
Ok. Suppose you have the following commands:
public class MoveCustomerCommand : ICommand
{
public int CustomerId { get; set; }
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) { }
public event EventHandler CanExecuteChanged;
}
public class KillCustomerCommand : ICommand
{
public int CustomerId { get; set; }
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) { }
public event EventHandler CanExecuteChanged;
}
Now consider the following architecture proposal for the handlers:
public abstract class CommandHandlerBase
{
protected static readonly Dictionary<Type, CommandHandlerBase> _handlers = new Dictionary<Type, CommandHandlerBase>();
protected abstract void HandleCommand<TCommand>(TCommand command) where TCommand: ICommand;
public static void Handle<TCommand>(TCommand command) where TCommand : ICommand
{
if (_handlers.TryGetValue(typeof(TCommand), out var handler))
{
handler.HandleCommand(command);
}
}
}
public abstract class CommandHandlerBase<TCommandHandlerBase, TCommand> : CommandHandlerBase
where TCommandHandlerBase : CommandHandlerBase<TCommandHandlerBase, TCommand>, new() where TCommand : ICommand
{
public static void Register()
{
var type = typeof(TCommand);
_handlers[type] = new TCommandHandlerBase();
}
protected override void HandleCommand<T>(T command) => Handle((TCommand) (object) command);
public abstract void Handle(TCommand command);
}
Basically what we do is to centralize all the handling into one base class, and we provide just an entry point for handling any TCommand (provided that there is a handler registered, you can put a default case or just crash if no handler is found).
The implementation may look confusing at first sight, but the usage is really nice after: we only define our handlers classes and we call Register. Let's see how they look:
public class MoveCustomerCommandHandler : CommandHandlerBase<MoveCustomerCommandHandler, MoveCustomerCommand>
{
public override void Handle(MoveCustomerCommand command) => Console.WriteLine("Moving the customer");
}
public class KillCustomerCommandHandler : CommandHandlerBase<KillCustomerCommandHandler, KillCustomerCommand>
{
public override void Handle(KillCustomerCommand command) => Console.WriteLine("Killing the customer");
}
And testing:
private static void Main(string[] args)
{
MoveCustomerCommandHandler.Register();
KillCustomerCommandHandler.Register();
CommandHandlerBase.Handle(new MoveCustomerCommand());
CommandHandlerBase.Handle(new KillCustomerCommand());
Console.ReadLine();
}
I think this approach is more maintainable and scalable, no need for reflection (with its performance hit), no need for very big switchs statements or hardcoded solutions.
Furthermore, you can add later an unregister method, or to keep more than one handler for a given command, the limit is the sky.. =)
Related
I have a Commander class, which handles commands. All these commands implement the ICommand interface. Basically the command pattern...
Now I want to create something similar to an event for each specific type of command, without actually making an event for each specific type in the commander. The commander should not be coupled to each type of command.
So my command has a method void Subscribe<T>(Action<T> callback) where T: ICommand. If a subscriber calls this with the method void MyAttackCommandHandler(AttackCommand att) as the parameter, I expect the subscriber to get a callback only for AttackCommands. However another class can also subscribe for a different command.
I tried creating a dictionary, that maps the type of the parameter (the kind of command) to a list of subscribers: Dictionary<Type, List<Action<ICommand>>> _subscriptions, and then my subscribe method would look something like:
public void Subscribe<T>(Action<T> callback)
where T: ICommand
{
Type type = typeof(T);
if (_subscriptions.ContainsKey(type))
{
List<Action<ICommand>> subscribtions = _subscriptions[type];
subscribtions.Add(callback);
}
else ... //create a new entry in _subscriptions
}
This however doesn't work because callback isn't of the type Action<ICommand>, but of Action<AttackCommand> for instance.
How would one implement this cleanly?
Thanks!
Try this
subscribtions.Add(i => callback((T)i));
If the above doesn't work please provide a full example that shows your problem.
Something like this:
using System;
using System.Collections.Generic;
namespace Example
{
class Program
{
static void Main(string[] args)
{
Commander C = new Commander();
C.Subscribe((MyCommand i) => { Console.WriteLine(i.Value); });
C.Subscribe((SquareMyCommand i) => { Console.WriteLine(i.Value); });
C.Subscribe((SquareMyCommand i) => { Console.WriteLine("**" + i.Value + "**"); });
C.Do(new MyCommand(2));//1 callback , Prints 2
C.Do(new SquareMyCommand(3));//2 callbacks, Prints 9 , **9**
Console.ReadLine();
}
}
public class Commander
{
Dictionary<Type, List<Action<ICommand>>> dictionary = new Dictionary<Type, List<Action<ICommand>>>();
public void Subscribe<T>(Action<T> callback) where T : ICommand
{
Type type = typeof(T);
List<Action<ICommand>> subscribtions = null;
dictionary.TryGetValue(type, out subscribtions);
if (subscribtions == null)
{
subscribtions = new List<Action<ICommand>>();
dictionary.Add(type, subscribtions);
}
subscribtions.Add(i => callback((T)i));
}
public void Do<T>(T t) where T : ICommand
{
foreach (var item in dictionary[t.GetType()])
item(t);
}
}
public class MyCommand : ICommand
{
public MyCommand(int x) { Value = x; }
public int Value { get; set; }
}
public class SquareMyCommand : ICommand
{
public SquareMyCommand(int x) { Value = x * x; }
public int Value { get; set; }
}
public interface ICommand
{
int Value { get; set; }
}
}
[Edited with more details at commenter request]
If I have the following:
myClassInstance.Register<MyCommand>(new MyCommandHandler().Handle);
I could of easily repeated the line above in different handlers.
However, I wonder is there a way to use Autofac to register them all generically through convention?
Here is code reflecting existing non-DI code:
public static class Program
{
public static void Main()
{
IMockBus bus = new MockBus();
var eventStore = new EventStore(bus);
var repository = new Repository<InventoryItem>(eventStore);
// Command
bus.RegisterHandler<CreateItem>(
new CreateItemCommandHandler(repository).Handle);
// Event
bus.RegisterHandler<ItemCreated>(
new ItemCreatedEventHandler().Handle);
}
}
public interface IMockBus
{
void RegisterHandler<T>(Action<T> handler) where T : IMessage;
}
public interface ISendCommands
{
void Send<T>(T command) where T : Command;
}
public abstract class Command : IMessage
{
}
public interface IMessage
{
}
public interface IPublishEvents
{
void Publish<T>(T #event) where T : Event;
}
public class Event : IMessage
{
public int Version;
}
public class MockBus : IMockBus
{
private readonly Dictionary<Type, List<Action<IMessage>>> routes =
new Dictionary<Type, List<Action<IMessage>>>();
public void RegisterHandler<T>(Action<T> handler) where T : IMessage
{
List<Action<IMessage>> handlers;
if (!routes.TryGetValue(typeof(T), out handlers))
{
handlers = new List<Action<IMessage>>();
routes.Add(typeof(T), handlers);
}
handlers.Add((message => handler((T)message)));
}
}
I want to create a generic mechanism for handling messages in C#. I have a need for this in my small application, so I don't want to use full blown message bus. My requirements are quite simple:
I want to have a couple of classes for messages i.e. Message1, Message2. They can inherit from one base class, that's not a problem, but if they don't I don't care. Currently they do inherit from Message.
be able to get handler for each and every message class. i.e. if I send Message1, then Message1Handler class should be instantiated. Handlers have to implement IMessageHandler<T> where T is the message class. IMessageHandler is defined as follows:
interface IMessageHandler<T>
{
void Execute(T message);
}
I wrote a simple "Resolver" class:
public static class HandlerRegistry
{
private static readonly Dictionary<string, Type> _handlers = new Dictionary<string, Type>();
public static void Register<T, T2>() where T2: IMessageHandler<T>
{
_handlers.Add(typeof(T).FullName, typeof(T2));
}
public static IMessageHandler<T> Resolve<T>(T parameters)
{
var type = _handlers[parameters.GetType().FullName];
return (IMessageHandler<T>) Activator.CreateInstance(type);
}
}
In this implementation everything is OK, but one part - the cast to IMessageHandler. When I'm trying to use this with a collection of messages this is what happens: the compiler doesn't know at compile time what actual messages are going to be in the collection - it just assumes that they are all subclasses of Message, so it's trying to cast IMessageHandler<ConcreteMessage> to IMessageHandler<Message> and obviously I'm getting an exception with invalid cast. In this case probably contravariance would help, but I'm not able to declare the parameter as out because I have the message in the Execute method parameters.
Does anyone know an elegant solution to this problem? I know I can make it "more runtime" - instead of using generics just declare
void Execute(Message m) and in each and every handler start with trying to cast to the type that I'm expecting, but as someone said somewhere - each and every cast that you write undermines the whole point of using a type system.
Option 1
If you do not care using reflection. You can add a Execute method to your HandlerRegistry instead of returning the handler back to the caller:
public static void Execute<T>(T parameters)
{
var type = _handlers[parameters.GetType().FullName];
var handler = Activator.CreateInstance(type);
type.GetMethod("Execute", new[] { parameters.GetType() })
.Invoke(handler, new object[] { parameters });
}
Option 2
If you do not care that one message handler can only subscribe to one message. We can take advantage of the Explicit Interface Implementation feature of C#:
// NOTE: This interface is not generic
public interface IMessageHandler
{
void Execute(object message);
}
public abstract class MessageHandler<T> : IMessageHandler
{
public abstract void Execute(T message);
// NOTE: Here we explicitly implement the IMessageHandler
void IMessageHandler.Execute(object message)
{
Execute((T)message);
}
}
Now your resolve method can change to:
public static IMessageHandler Resolve<T>(T parameters)
{
var type = _handlers[parameters.GetType().FullName];
return (IMessageHandler)Activator.CreateInstance(type);
}
By the way, personally I would prefer to pass in a Type instead of the message instance.
Then make your handlers inherit from the generic abstract MessageHandler<T> instead of implementing IMessageHandler:
public class HandlerA : MessageHandler<MessageA>
{
public override void Execute(MessageA message)
{
Console.WriteLine("Message A");
}
}
public class HandlerB : MessageHandler<MessageB>
{
public override void Execute(MessageB message)
{
Console.WriteLine("Message B");
}
}
How about this for a message router:
class Tester
{
public void Go()
{
var a = new MessageA();
var b = new MessageB();
var c = new MessageC();
var router = new MessageRouter();
router.RegisterHandler(new HandlerA());
router.RegisterHandler(new HandlerB());
router.Route(a);
router.Route(b);
router.Route(c);
}
}
class MessageRouter
{
Dictionary<Type, dynamic> m_handlers = new Dictionary<Type,dynamic>();
public void RegisterHandler<T>(IMessageHandler<T> handler)
{
m_handlers.Add(typeof(T), handler);
}
public void Route(dynamic message)
{
var messageType = message.GetType();
if (m_handlers.ContainsKey(messageType))
{
m_handlers[messageType].Handle(message);
}
else
{
foreach (var pair in m_handlers)
{
if(pair.Key.IsAssignableFrom(messageType))
{
pair.Value.Handle(message);
}
}
}
}
}
class MessageA
{
public virtual string A { get { return "A"; } }
}
class MessageB
{
public string B { get { return "B"; } }
}
class MessageC :MessageA
{
public override string A { get { return "C"; } }
}
interface IMessageHandler<T>
{
void Handle(T message);
}
class HandlerA : IMessageHandler<MessageA>
{
public void Handle(MessageA message)
{
Console.WriteLine(message.A);
}
}
class HandlerB : IMessageHandler<MessageB>
{
public void Handle(MessageB message)
{
Console.WriteLine(message.B);
}
}
How about taking a slightly different approach: Instead of registering the type of a handler, why not register the actual handler instance which will process the message? This gives you much greater flexibility in instantiation of the handler, and removes any type ambiguities.
The idea is to be able to do this:
// have several handler classes
class FooMessageHandler : IMessageHandler<Foo>
{ }
class BarMessageHandler : IMessageHandler<Bar>
{ }
// have them instantiated - allows you to pass much more context
// than Activator.CreateInstance is able to do
var fooMessageHandler = new FooMessageHandler(various params);
var barMessageHandler = new BarMessageHandler(various params);
// register actual instances
HandlerRegistry.Register<Foo>(fooMessageHandler);
HandlerRegistry.Register<Bar>(barMessageHandler);
// handler registry will simply dispatch the message to
// one of the handlers
HandlerRegistry.Dispatch(someFooMessage);
Not only that, but the approach allows you to register multiple handlers for each message type:
// these will all get called when a Foo message is received
HandlerRegistry.Register<Foo>(fooMessageHandler);
HandlerRegistry.Register<Foo>(someOtherFooHandler);
HandlerRegistry.Register<Foo>(yetAnotherFooHandler);
What if you inherit all you messages from common abstract MessageBase and instead of making message handler interface IMessageHandler<T> generic, put constraint on Execute method itself?
Namely void Execute<T>(T message) where T : MessageBase.
This way you get the desired functionality and your message handler resolver, HandlerRegistry, needs only a minor tweak. Just change return type & constraint from IMessageHandler<T> to IMessageHandler.
Below are slightly modified MessageBase, IMessageHandler and HandlerRegistry.
(Related dotnetfiddle here https://dotnetfiddle.net/e6M1UA)
// Message
public abstract class MessageBase
{
public virtual void Action() // ...for examples sake
{
Console.WriteLine(GetType().Name);
}
}
// Message handler
public interface IMessageHandler
{
void Execute<T>(T message) where T : MessageBase;
}
// Resolver
public static class HandlerRegistry
{
private static readonly Dictionary<string, Type> Handlers =
new Dictionary<string, Type>();
public static void Register<T, T2>() where T2 : IMessageHandler
{
Handlers.Add(typeof(T).FullName, typeof(T2));
}
public static IMessageHandler Resolve<T>(T parameters)
{
var type = Handlers[parameters.GetType().FullName];
return (IMessageHandler)Activator.CreateInstance(type);
}
}
Now, if you test it using e.g. following implementations
public class Message1 : MessageBase
{}
public class Message2 : MessageBase
{
public override void Action()
{
Console.Write(#"Overriding ");
base.Action();
}
}
public class Message1Handler : IMessageHandler
{
public void Execute<T>(T message) where T : MessageBase
{
Console.Write(#"MessageHandler1 > ");
message.Action();
}
}
public class Message2Handler : IMessageHandler
{
public void Execute<T>(T message) where T : MessageBase
{
Console.Write(#"MessageHandler2 > ");
message.Action();
Console.WriteLine(#"...and then some");
}
}
With this block of code
HandlerRegistry.Register<Message1, Message1Handler>();
HandlerRegistry.Register<Message2, Message2Handler>();
var messages = new List<MessageBase>()
{
new Message1(),
new Message2()
};
foreach (var message in messages)
{
var handler = HandlerRegistry.Resolve(message);
handler.Execute(message);
}
You'll end up with console log
MessageHandler1 > Message1
MessageHandler2 > Overriding Message2
...and then some
What i'm trying to accomplish is to have a single wcf service that has (for example) an Insert(ICommand command) method and can resolve a generic service that knows how to insert the underling object type.
Where's my (poor) attempt on a sandbox project.
Besides other flaws, this services allow to attempt to insert any ICommand.
I'm relative new Unit user and i was wondering if someone has a better way to accomplish this.
class Program
{
static void Main(string[] args)
{
var cmd = new SingleCommand();
var cmd2 = new DoubleCommand();
var s = new MyWcfService();
s.Insert(cmd);
s.Insert(cmd2);
Console.ReadKey();
}
}
public interface ICommand { }
public interface ICommandService
{
void Insert(ICommand command);
}
public interface ICommandService<in T> : ICommandService where T : ICommand
{
void Insert(T command);
}
public class SingleCommand : ICommand { }
public class DoubleCommand : ICommand { }
public class SingleCommandService : ICommandService<SingleCommand>
{
public void Insert(SingleCommand singleCommand)
{
Console.WriteLine("Inserted a SingleCommand");
}
void ICommandService.Insert(ICommand command)
{
Insert((SingleCommand)command);
}
}
public class DoubleCommandService : ICommandService<DoubleCommand>
{
public void Insert(DoubleCommand doubleCommand)
{
Console.WriteLine("Inserted a DoubleCommand");
}
void ICommandService.Insert(ICommand command)
{
Insert((DoubleCommand)command);
}
}
public static class Config
{
public static UnityContainer Container = new UnityContainer();
static Config()
{
Container.RegisterType<ICommandService, SingleCommandService>(typeof(SingleCommand).Name);
Container.RegisterType<ICommandService, DoubleCommandService>(typeof(DoubleCommand).Name);
}
}
public class MyWcfService
{
public void Insert(ICommand command)
{
var foo = Config.Container.Resolve<ICommandService>(command.GetType().Name);
foo.Insert(command);
}
}
If you really don't have a service that can be invoked for all ICommand, then you shouldn't offer that in its contract. An easy way around this is to extend the ICommand interface into something like IServiceCommand, and have those ICommand which are supported implement IServiceCommand instead, and tie your service contract instead to that interface. This allows your concrete classes to be used in any method which expects an ICommand, but your service still only service those ICommand which are also IServiceCommand.
Problem:
in my domain layer assembly I store two interfaces:
public interface IDomainEvent { }
and
public interface IHandle<T> where T: IDomainEvent, new()
EventDispatcher class is defined there also:
public static class EventDispatcher {
[ThreadStatic]
private static List<Delegate> actions;
[ThreadStatic]
private static List<Object> handlers;
public static List<Object> Handlers {
get { return handlers; }
set { handlers = value; }
}
public static void Register<T>(Action<T> callback) where T : IDomainEvent, new() {
if(null == actions) {
actions = new List<Delegate>();
actions.Add(callback);
}
}
public static void ClearCallbacks() {
actions = null;
}
public static void Raise<T>(T #event) where T : IDomainEvent, new() {
if(null != Handlers) {
foreach(var handler in Handlers.Where(h => h is IHandle<T>)) {
((IHandle<T>)handler).Handle(#event);
}
}
if(null != actions) {
foreach(var action in actions) {
if(action is Action<T>) {
((Action<T>)action)(#event);
}
}
} // if(null != actions) {
}
}
There's a module in presentation layer assembly:
public class EventDispatchingModule : NinjectModule {
public override void Load() {
// EventDispatcher.Handlers = this.Kernel.GetAll(IHandle<T>); Can't do that!
// Bind<IHandle<CarHasBeenRegisteredEvent>>().To<CarHasBeenRegisteredHandler();
}
}
So I can't call Kernel.GetAll(IHandle<T>) there because it can't resolve T parameter.
Howcome I resolve this?
Thanks!
No need to use a module (I've not used ninject, but something similar):
// Put these in the domain project
public class EventDispatcher
{
private static IEventDispatcher _dispatcher;
public static void Setup(IEventDispatcher dispatcher)
{
_dispatcher = dispatcher;
}
public static void Dispatch<T>(T domainEvent) where T : IDomainEvent
{
_dispatcher.Dispatch<T>(domainEvent);
}
}
public interface IEventDispatcher
{
public void Dispatch<T>(T domainEvent) where T : IDomainEvent;
}
// and this one in the project which has Ninject
public class NinjectEventDispatcher : IEventDispatcher
{
private static IKernel _container;
public NinjectEventDispatcher(IKernel container)
{
_container = container;
}
public void Dispatch<T>(T domainEvent) where T : IDomainEvent
{
foreach (var listener in _container.GetAll<IHandle<T>>())
{
listener.Handle(domainEvent);
}
}
}
// And after the container have been configured:
EventDispatcher.Setup(new NinjectEventDispatcher(_container));
But I don't know how ninject handles scoped objects (which may also want to receive the events).
My container has domain events built in, read more in this article: http://www.codeproject.com/Articles/440665/Having-fun-with-Griffin-Container
Update:
I've updated the code sample to make the domain project unaware of Ninject.
You are not using Service Location with this code. The internals of the event dispatcher is. i.e. none of your code is affected by it.
You can get all Handlers with following code
Kernel.GetAll(typeof (IHandle<>));
But anyway it's not good idea to load all IHanders in NInjectModule because you don't know if another modules are already loaded or not (and another modules can register Handlers too).
I suggest make EventDispatcher class not static and register it in scope that you need (If you need new handlers for each request - in request scope, otherwise - in singleton scope . Handlers you can inject with constructor like :
Kerner.Bind<EventDispatcher>().ToSelf()
.InRequestScope()
.WithConstructorArgument("handlers", c => c.Kernel.GetAll(typeof(IHandler<>)))
Hope this helps