The interfaces,commands and command handler set up as per instructions in Simpleinjector wiki.
public interface ICommand
{
string Name { get; set; }
}
public class Command1 : ICommand
{
public string Name { get; set; }
}
public class Command2 : ICommand
{
public string Name { get; set; }
}
public interface ICommandHandler<TCommand>
{
void Execute(TCommand Command);
}
public class Command1Handler : ICommandHandler<Command1>
{
public void Execute(Command1 Command) {
Console.WriteLine(Command.Name);
}
}
public class Command2Handler : ICommandHandler<Command2>
{
public void Execute(Command2 Command) {
Console.WriteLine(Command.Name + "Hello");
}
}
Decorator:
public class CommandDecorator<TCommand> : ICommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> _handler;
public CommandDecorator(ICommandHandler<TCommand> handler)
{
this._handler = handler;
}
public void Execute(TCommand command)
{
this._handler.Execute(command);
}
}
Sample program
public class Program
{
static void Main(string[] args)
{
Container container = new Container();
//registering
container.RegisterAll<ICommand>(typeof(Command1), typeof(Command2));
container.RegisterManyForOpenGeneric(
typeof(ICommandHandler<>),
typeof(ICommandHandler<>).Assembly);
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(CommandDecorator<>));
container.Verify();
// sample test command
ICommand testcommand = new Command2();
testcommand.Name = "command 1";
var type = typeof(ICommandHandler<>).MakeGenericType(testcommand.GetType());
dynamic instance = container.GetInstance(type);
instance.Execute((dynamic)testcommand);
}
}
Is this the right way to get the right handler for handling the command at runtime.
This is a sample and in the real app the commands are going to posted to a queue and a service is going to read the command and process it .
I guess the Decorator has to be used for that but am not able to get it working.
please suggest better options if any.
Your commands (Command1 and Command2) are not services: they should not be registered. They are runtime data (message) that you pass through your services (your command handlers). So you should remove the Collection.Register<ICommand> (RegisterAll in v2) registration. It is of no use. You already see its of no use, since in your example you are newing the Command2 up manually, which is the right thing to do.
What you are doing in the last three lines of code is dispatching a command of an unknown type to the right command handler registration. You always need some reflection to pull this of, since you need to build the closed ICommandHandler<TCommand> type based on the command type, which is something you don't know at compile time. Instead of using the C# dynamic keyword, you can also use the .NET reflection API, but in my experience using dynamic is better in this particular case. One important downside of the reflection API is that the API will always wrap any thrown exception (in case of a failure) with an InvocationException and that makes it harder to do certain exception handling up the call stack.
So long story short, this should be your registration:
Container container = new Container();
container.Register(
typeof(ICommandHandler<>),
typeof(ICommandHandler<>).Assembly);
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(CommandDecorator<>));
And this should be the dispatching logic:
var type = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
dynamic handler = container.GetInstance(type);
handler.Execute((dynamic)command);
Related
I want to implement a CommandBus that can Dispatch some Commands to CommandHandlers.
A Command is a simple a DTO describing what should happen. For instance : "Increment counter by 5"
A CommandHandler is able to handle a precise type of Command.
The CommandBus takes a Command and executes the CommandHandler that is able to handle it.
The code I wrote does not compile.
Compiler complains cannot convert from 'IncrementHandler' to 'Handler<Command>'.
I don't understand why, because IncrementHandler implements Handler<Increment> and Increment implements Command
I've tried both in and out modifiers on the generic interfaces, it doesn't solve the problem.
Is there a way to achieve this with only interfaces ?
[TestClass]
public class CommandBusTest
{
[TestMethod]
public void DispatchesProperly()
{
var handler = new IncrementHandler(counter: 0);
var bus = new CommandBus(handler); // <--Doesn't compile: cannot convert from 'IncrementHandler' to 'Handler<Command>'
bus.Dispatch(new Increment(5));
Assert.AreEqual(5, handler.Counter);
}
}
public class CommandBus
{
private readonly Dictionary<Type, Handler<Command>> handlers;
public CommandBus(params Handler<Command>[] handlers)
{
this.handlers = handlers.ToDictionary(
h => h.HandledCommand,
h => h);
}
public void Dispatch(Command commande) { /*...*/ }
}
public interface Command { }
public interface Handler<TCommand> where TCommand : Command
{
Type HandledCommand { get; }
void Handle(TCommand command);
}
public class Increment : Command
{
public Increment(int value) { Value = value; }
public int Value { get; }
}
public class IncrementHandler : Handler<Increment>
{
// Handler<Increment>
public Type HandledCommand => typeof(Increment);
public void Handle(Increment command)
{
Counter += command.Value;
}
// Handler<Increment>
public int Counter { get; private set; }
public IncrementHandler(int counter)
{
Counter = counter;
}
}
I don't understand why, because IncrementHandler implements Handler<Increment> and Increment implements Command
Let's fix your misunderstanding, and then the rest will become clear.
Suppose what you wanted to do was legal. What goes wrong?
IncrementHandler ih = whatever;
Handler<Command> h = ih; // This is illegal. Suppose it is legal.
now we make a class
public class Decrement : Command { ... }
And now we pass it to h:
Decrement d = new Decrement();
h.Handle(d);
This is legal, because Handler<Command>.Handle takes a Command, and a Decrement is a Command.
So what happened? You just passed a decrement command to ih, via h, but ih is an IncrementHandler that only knows how to handle increments.
Since that is nonsensical, something in here has to be illegal; which line would you like to be illegal? The C# team decided that the conversion is the thing that should be illegal.
More specifically:
Your program is using reflection in an attempted end-run around the type system's safety checks, and then you are complaining that the type system is stopping you when you write something unsafe. Why are you using generics at all?
Generics are (in part) to ensure type safety, and then you are doing a dispatch based on reflection. This doesn't make any sense; don't take steps to increase type safety and then do heroic efforts to work around them.
Plainly you wish to work around type safety, so don't use generics at all. Just make an ICommand interface and a Handler class that takes a command, and then have some mechanism for working out how to dispatch commands.
What I don't understand though is why there are two kinds of things at all. If you want to execute a command, then why not simply put the execution logic on the command object?
There are also other design patterns you could use here other than this clunky dictionary lookup based on types. For example:
a command handler could have a method that takes a command and returns a boolean, whether the handler can handle this command or not. Now you have a list of command handlers, a command comes in, and you just run down the list asking "are you my handler?" until you find one. If O(n) lookup is too slow, then build a MRU cache or memoize the result or some such thing, and the amortized behaviour will improve.
the dispatch logic could be put into the command handler itself. A command handler is given a command; it either executes it, or it recurses, calling its parent command handler. You can thus build a graph of command handlers that defer work to each other as necessary. (This is basically how QueryService works in COM.)
The problem here is that Increment implements Command (which I renamed to ICommand to make that clearer, in the code below).
So it is no longer accepted as a Handler<Command>, which is what the constructor expects (subtype instead of required supertype, as #Lee pointed out in comments).
If you can generalize to use just ICommand, it would work:
public class CommandBusTest
{
public void DispatchesProperly()
{
var handler = new IncrementHandler(counter: 0);
var bus = new CommandBus((IHandler<ICommand>)handler);
bus.Dispatch(new Increment(5));
}
}
public class CommandBus
{
private readonly Dictionary<Type, IHandler<ICommand>> handlers;
public CommandBus(params IHandler<ICommand>[] handlers)
{
this.handlers = handlers.ToDictionary(
h => h.HandledCommand,
h => h);
}
public void Dispatch(ICommand commande) { /*...*/ }
}
public interface ICommand { int Value { get; } }
public interface IHandler<TCommand> where TCommand : ICommand
{
Type HandledCommand { get; }
void Handle(TCommand command);
}
public class Increment : ICommand
{
public Increment(int value) { Value = value; }
public int Value { get; }
}
public class IncrementHandler : IHandler<ICommand>
{
// Handler<ICommand>
public Type HandledCommand => typeof(Increment);
public void Handle(ICommand command)
{
Counter += command.Value;
}
// Handler<ICommand>
public int Counter { get; private set; }
public IncrementHandler(int counter)
{
Counter = counter;
}
}
The problem here is that your definition of Handler<TCommand> requires TCommand to be both covariant and contravariant - and that's not allowed.
To pass a Handler<Increment> into the constructor of CommandBus (which expects a Handler<Command>), you must declare Command as a covariant type parameter in Handler, like this:
public interface Handler<out TCommand> where TCommand : Command
Making this change allows you to pass in a Handler<AnythingThatImplementsCommand> wherever a Handler<Command> is requested, so your constructor for CommandBus works now.
But this introduces a new issue for the following line:
void Handle(TCommand command);
Since TCommand is covariant, it is possible to assign a Handler<Increment> to a Handler<Command> reference. Then you would be able to call the Handle method but pass in anything that implements Command - clearly that's not going to work. To make this call correct, you have to allow TCommand to be contravariant instead.
Since you can't do both, you'll have to make a concession somewhere. One way to do this is by making using covariance in Handler<TCommand>, but force an explicit cast in your Handle method, like this:
public interface Handler<out TCommand> where TCommand : Command
{
Type HandledCommand { get; }
void Handle(Command command);
}
public class IncrementHandler : Handler<Increment>
{
public void Handle(Command command)
{
Counter += ((Increment)command).Value;
}
}
It doesn't prevent somebody from creating an IncrementHandler and then passing in the wrong kind of Command, but if the handlers are only used by CommandBus you can check the type in CommandBus.Dispatch and have something resembling type safety.
Lets assume these classes/interfaces:
public interface ICommand
{
}
public class SomeCommand : ICommand
{
}
public interface ICommandHandler<T> where T : ICommand
{
void Handle(T arg);
}
public class SomeCommandHandler : ICommandHandler<SomeCommand>
{
void Handle(SomeCommand arg){ /* do something */ }
}
public interface ICommandBus
{
void RegisterHandler<T>(T t) where T : ICommandHandler<T>;
void RegisterHandlerByParam<T2>(ICommandHandler<T2> t2) where T2 : ICommand;
void RegisterHandlerMethod<T3>(Action<T3> action) where T3 : ICommand
}
public class TheCommandBus : ICommandBus
{
// implements ICommandBus ...
}
I want to register all implementations of ICommandHandler<> automatically.
All variants (Register*) are valid solutions even though I would prefer Action parameter while it is more flexible and has no dependency to Handler interface (just action delegate).
Autofac has the capability to register types based upon assembly scanning and register the found implementations of a generic interface, for example:
builder.RegisterAssemblyTypes(Assembly.LoadFrom("MyAssembly.dll"))
.AsClosedTypesOf(typeof(ICommandHandler<>));
So I have all implementations registered. Now I need to Register them all automatically to TheCommandBus. How to do that?
I can do this manually by adding those lines (e.g. during OnActivated):
builder.RegisterType<TheCommandBus>().As<ICommandBus>().OnActivated(args =>
{
// now I need to list all implementations here!!! please, no...
args.Instance.RegisterHandler<ICommandHandler<SomeCommand>>(args.Context.Resolve<ICommandHandler<SomeCommand>>());
// does not look better to me than before ...
args.Instance.RegisterHandlerByParam<SomeCommand>(args.Context.Resolve<ICommandHandler<SomeCommand>>())
// uses delegate for, but still need to list all variants
args.Instance.RegisterHandlerMethod<SomeCommand>(args.Context.Resolve<ICommandHandler<SomeCommand>>().Handle)
});
If I want to use such a type in a lambda expression during registration I have the problem, that I need to identify the concrete type, like for this example on activation process for another component. But I don't want to list all of them manually... want something like this automatically.
How do I catch all ICommandHandler implementations AND have them automatically registered with the Register* method?
Edit:
Another variant is to extend the SomeCommandHandler class to register itself when resolved inside its constructor:
public SomeCommandHandler(ICommandBus commandBus)
{
// and register here, for example
commandBus.RegisterHandlerbyParam(this);
}
This way I have to provide AutoActivate() to the AsClosedTypesOf registration result. (a possible solution, but now the "handlers" have two responsibilities... registration and handling)
This is an interesting and tricky problem. The generics definitely add to that complexity since going non-generic would be a simple IEnumerable<T> resolution.
But... I think I can help.
You'll take advantage of...
The OnRegistered event in RegisterAssemblyTypes so you can look at what was actually registered.
The OnActivating event for the bus so you can do the registration of the handlers.
Closures to carry the list of registered handler types into the OnActivating event.
Some fancy-schmancy reflection to create the closed generic version(s) of the RegisterHandler method on the bus.
Here's a full, working example showing how to do it. Note I had to change the ICommandBus interface for RegisterHandler a bit since it wouldn't compile for me in the originally listed form, but you should be able to adapt as needed. I ran this in ScriptCs to verify.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autofac;
public interface ICommand { }
public class CommandOne : ICommand { }
public class CommandTwo : ICommand { }
public interface ICommandHandler<T> where T : ICommand
{
void Handle(T arg);
}
public class CommandOneHandler : ICommandHandler<CommandOne>
{
public void Handle(CommandOne arg) { }
}
public class CommandTwoHandler : ICommandHandler<CommandTwo>
{
public void Handle(CommandTwo arg) { }
}
public interface ICommandBus
{
IEnumerable<object> Handlers { get; }
void RegisterHandler<TCommand, THandler>(THandler handler)
where THandler : ICommandHandler<TCommand>
where TCommand : ICommand;
}
public class CommandBus : ICommandBus
{
private readonly List<object> _handlers = new List<object>();
public IEnumerable<object> Handlers
{
get
{
return this._handlers;
}
}
public void RegisterHandler<TCommand, THandler>(THandler handler)
where THandler : ICommandHandler<TCommand>
where TCommand : ICommand
{
this._handlers.Add(handler);
}
}
var builder = new ContainerBuilder();
// Track the list of registered command types.
var registeredHandlerTypes = new List<Type>();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.AsClosedTypesOf(typeof(ICommandHandler<>))
.OnRegistered(e => registeredHandlerTypes.Add(e.ComponentRegistration.Activator.LimitType));
// Initialize the bus by registering handlers on activating.
builder.RegisterType<CommandBus>()
.As<ICommandBus>()
.OnActivating(e => {
foreach(var handlerType in registeredHandlerTypes)
{
// Due to the generic method, some crazy reflection happens.
// First, get ICommandHandler<T> interface.
var handlerInterfaceType = handlerType.GetInterface("ICommandHandler`1");
// Grab the <T> from the ICommandHandler<T>.
var commandType = handlerInterfaceType.GetGenericArguments()[0];
// Build the closed generic version of RegisterHandler<TCommand, THandler>.
var registerMethod = typeof(ICommandBus).GetMethod("RegisterHandler").MakeGenericMethod(commandType, handlerType);
// Call the closed generic RegisterHandler<TCommand, THandler> to register the handler.
registerMethod.Invoke(e.Instance, new object[] { e.Context.Resolve(handlerInterfaceType) });
}
})
.SingleInstance();
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
var bus = scope.Resolve<ICommandBus>();
foreach(var t in bus.Handlers)
{
// List the handler types registered.
Console.WriteLine(t.GetType());
}
}
Follow up to an older question here. Say I have a registration like the following:
container.Register(typeof(IHandleCommand<>), _handlerAssemblies, Lifestyle.Transient);
container.RegisterDecorator(typeof(IHandleCommand<>),
typeof(MetricsCommandHandlerWrapper<>), Lifestyle.Singleton);
Where the MetricsCommandHandlerWrapper is defined like so:
public class MetricsCommandHandlerWrapper<T> : IHandleCommand<T> where T: ICommand
{
private readonly ICollectMetrics _metrics;
private readonly Func<IHandleCommand<T>> _handlerFactory;
public MetricsCommandHandlerWrapper(ICollectMetrics metrics,
Func<IHandleCommand<T>> handlerFactory)
{
_metrics = metrics;
_handlerFactory = handlerFactory;
}
public async Task HandleAsync(T command)
{
// code to record metrics around command handling which eventually invokes
await _handlerFactory().HandleAsync(command).ConfigureAwait(false);
}
}
How can I write a unit test that asserts the actual decoratee handlers are registered with Transient lifestyle?
I have tried composing the root and inspecting the registration for a closed IHandleCommand<FakeCommand> type, which reveals an ImplementationType of MetricsCommandHandlerWrapper<FakeCommand> as expected. Invoking GetRelationships() on that registration reveals its 2 dependencies, ICollectMetrics and the one I am interested in, the Func<IHandleCommand<FakeCommand>> factory delegate, which is registered as a Singleton. However invoking .Dependency.GetInstance() on that factory delegate throws an exception that the instance producer returned null.
Is there any way to assert that the inner decoratee is registered as Transient, and if so, how?
The use of the Func<T> delays the building of the object graph, and from perspective of the diagnostic system, the graphs stops at that point. So, it's not possible to do this analysis.
Instead of completely relying on Simple Injector's internals however, you can also choose to make some minor changing in your application to allow testing decorators.
What you can do is implement an IDecorator abstraction on your decorators:
public interface IDecorator {
object Decoratee { get; }
}
Now each decorator can implement this interface. For the MetricsCommandHandlerWrapper<T>, it might look as follows:
public class MetricsCommandHandlerWrapper<T> : IHandleCommand<T>, IDecorator where T: ICommand
{
private readonly ICollectMetrics _metrics;
private readonly Func<IHandleCommand<T>> _handlerFactory;
public MetricsCommandHandlerWrapper(ICollectMetrics metrics,
Func<IHandleCommand<T>> handlerFactory) {
_metrics = metrics;
_handlerFactory = handlerFactory;
}
public object Decoratee { get { return _handlerFactory(); }
public async Task HandleAsync(T command) { ... }
}
On top of the IDecorator interface, you can define a simple extension method:
public static IEnumerable<Type> GetDecoratorChain(this IDecorator decorator) {
while (decorator != null) {
yield return decorator.GetType();
decorator = decorator.Decoratee as IDecorator;
}
}
Inside your unit test you can now resolve a handler and ask for the list of applied decorators. Using this list you can verify whether decorators are applied in the correct order.
So i am using a decorator to print after certain commands are handled. My issue is if the user wants to issue a reprint. I created a Reprint command class that gets sent from the UI layer, but the Reprint command does not need a separate handler from the PrintDecorator since the reprint handling is exactly everything in the print decorator. Is there a strategy to target the PrintDecorator only with SimpleInjector? I know this probably goes against the pattern, but the only way I could think of was to create an empty command handler for the reprint command, but that does not seem right. Thanks.
public class Reprint : ICommandParam, IPrintFrom
{
public string Id { get; set; }
public string Printer { get; set; }
public int Copies { get; set; }
}
public class PrintDecorator<TCommand> : ICommandHandler<TCommand>
where TCommand : IPrintFrom
{
private readonly IFooService _svc;
private readonly ICommandHandler<TCommand> _handler;
public PrintDecorator(IFooService svc, ICommandHandler<TCommand> handler)
{
if (svc == null)
throw new ArgumentNullException("IFooService");
_svc = svc;
_handler = handler;
}
[Import] // optional
public IDatabase Database { get; set; }
public void Handle(TCommand commandParm)
{
if (_handler != null)
_handler.Handle(commandParm);
svc.GetDataFromService(commandParm.id);
svc.PrintData(commandParm.Printer, commandParm.Copies);
if (Database != null && commandParm.Copies > 0) {
// TODO - add a print record
}
}
}
It all depends on what you want. My suggestion is to keep the reprinting logic inside a real ReprintCommandHandler (probably by injecting a service that does the printing the same way you would do with the decorator). This seems reasonable to me, because in the case of reprinting, the reprinting is the actual business logic, and not a cross-cutting concern.
In this case you will have to exclude the PrintDecorator from being decorated around your ReprintCommandHandler and this can be done as follows:
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(PrintDecorator<>),
c => c.ServiceType != typeof(ICommandHandler<Reprint>));
If on the other hand, you want to keep the printing logic inside the PrintDecorator without having to duplicate this logic inside your business layer, you can either implement a completely empty ReprintCommandHandler, or you can register a special Null Object command handler.
Using the empty handler is of course Simple and will make your configuration really straightforward:
// NOTE: Use RegisterManyForOpenGeneric for Simple Injector v2.x
container.Register(typeof(ICommandHandler<>),
new[] { typeof(ICommandHandler<>).Assembly });
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(PrintDecorator<>));
Downside is of course that you need an empty class for this. So the alternative is to implement the Null Object pattern as follows:
public class NullCommandHandler<T> : ICommandHandler<T> {
public void Handle(T command) { }
}
This implementation can be reused in case you have multiple empty implementations and you can register this as follows:
// NOTE: Use RegisterManyForOpenGeneric for Simple Injector v2.x
container.Register(typeof(ICommandHandler<>),
new[] { typeof(ICommandHandler<>).Assembly });
container.Register<ICommandHandler<Reprint>, NullCommandHandler<Reprint>>();
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(PrintDecorator<>));
Trying to build a CQRS solution, I have the following code trying to find a Handler and then invoke a Handle() method.
The code below works but it's annoying to use reflection when we know that all IHandleCommand<> have a Handle method, this could be resolved at compiletime, I belive!
Do I have to use dynamic in some way?
public void SendCommand(Command command)
{
Type handlerType = typeof(IHandleCommand<>).MakeGenericType(command.GetType());
object handler = container.Resolve(handlerType);
handler.GetType().GetMethod("Handle").Invoke(handler, new object[] { command });
}
Here's the other types used above
public class Command {}
public class MyCommand : Command {}
public interface IHandleCommand<T>
{
void Handle(T command);
}
public class MyCommandHandler : IHandleCommand<MyCommand>
{
public void Handle(MyCommand command) {}
}
I made something similar to that where I used a container (StructureMap in my case) to get handler instances from.
Check out that question and its answers: StructureMap register generic types against all possible concrete implementations
I used Autofac to solve the problem.Here is what I ended up with
Assuming this interface
public interface IHandleCommand<T> where T : Command
{
void Handle(T command);
}
The Servicebus will call something like this
private readonly IComponentContext container;
public InProcessBus(IComponentContext container)
{
this.container = container;
}
public void Send<T>(T command) where T : Command
{
if (command == null) throw new ArgumentNullException("Command");
container.Resolve<IHandleCommand<T>>().Handle(command);
}
and my Autofac CommandsHandlersModule
public class CommandsHandlersModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(CartCommandsHandler).Assembly)
.AsClosedTypesOf(typeof(IHandleCommand<>))
.SingleInstance();
}
}
Than from your app you call
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new CommandsHandlersModule());
After playing around I found out some solutions:
dynamic handler = container.Resolve(handlerType);
handler.Handle(command as dynamic);
But if I send command as dynamic to a generic method I will get Command as it's real type as T to do magic with. Also the call to Handle() can be resolved at compile time. Then there's no need for generic covariant casting, which turns out to be problem from the beginning.
public void SendCommand(Command command)
{
Invoke(command as dynamic);
}
private void Invoke<T>(T command) where T : Command
{
var handler = container.Resolve<IHandleCommand<T>>();
handler.Handle(command);
}
It is really nice, but I won't go entirely for that solution since I don't registrate command handlers, i'll use this:
private void Invoke<T>(T command) where T : Command
{
Type handlerType = CommandToHandlerType(command);
var handler = (IHandleCommand<T>)container.Resolve(handlerType);
handler.Handle(command);
}
CommandToHandlerType() just searches an assembly for a type implementing IHandleCommand of T