Interface covariance contravariance : why is this not compiling? - c#

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.

Related

Derived constructor with type parameter

EDIT: added follow up question from getting a solution suggested from another question
EDIT2: I just realised that my follow up question was not needed.
Is it possible to have an abstract base class with a type parameter of T have a constructor that takes a parameter of T and assigns it to a property of T? What i want to achieve is that all derived classes has a constructor that does this?
Something like:
public abstract class NotificationBase <T>
{
public string Text { get; set; }
public T Context { get; set; }
public NotificationBase(T context, string text)
{
Context = context;
Text = text;
}
}
public class NumberNotification : NotificationBase<int>{}
public class Program
{
public void Run()
{
var thing = new NumberNotification(10, "Hello!");
}
}
EDIT:
I got a link to another question that explained how to do this which is great. However i have some issues with that. And i dont mean its wrong, if that is the only way to do it then thats how it is. However its not the ideal situation for what im trying to do. I explain. This was the solution:
public class Base
{
public Base(Parameter p)
{
Init(p)
}
void Init(Parameter p)
{
// common initialisation code
}
}
public class Derived : Base
{
public Derived(Parameter p) : base(p)
{
}
}
..which works great. However it does create two small issues that id like to se if they can be addressed.
What i want is to force all classes that derives from the base to pass a T into the constructor so that its mandatory. With this solution, its possible to leave it out.
If all classes should do this then it feels redundant to create a constructor to propagate a mandatory parameter.
EDIT: I just realised that demanding a constructor that propagates the type parameter IS what im looking for. I makes sure that the T property gets a value and also allows for other things to happen in the constructor.
Yes, you can, you just need to propagate the constructor chain using the relevant type, and call the ancestor if needed:
public class NumberNotification : NotificationBase<int>
{
public NumberNotification(int context, string text)
: base(context, text)
{
}
}
Without constructor in child class, the instantiation you wrote can't compile because you don't offer a way for the compiler to know what to do.
You can also offer any other constructor needed.
Therefore now this compiles and works:
var thing = new NumberNotification(10, "Hello!");
Inheritance And Constructors (C# Corner)
base (C# Reference)
Define the parameterized constructor for NumberNotification class which should invoke the required constructor of NotificationBase using base
public class NumberNotification : NotificationBase<int>
{
public NumberNotification(int context, string text)
:base(context, text)
{
}
}
Now for NumberNotification object, context is type of int as here T is marked as int type which Yyou can check using below code:
var thing = new NumberNotification(10, "Hello!");
Console.WriteLine(thing.Context.GetType());
The above prints the output as System.Int32
Check the fiddle - https://dotnetfiddle.net/keufQO

Lambda implementing Interface

In the book I'm reading "Head First Design Patterns", Command Pattern there is an example where they're substituting an Interface with Lambda.
Is this something that only Java is capable of?
Here is an example
From the book:
// Receiver
public class Light
{
public void On() {
Console.WriteLine("Lights on");
}
public void Off() {
Console.WriteLine("Ligts off");
}
}
// Command interface
public interface ICommand
{
void Execute();
}
// Concrete command
public class SimpleCommandLightOn : ICommand
{
private readonly Light light;
public SimpleCommandLightOn(Light light) {
this.light = light;
}
public void Execute() {
light.On();
}
}
// Concrete command
public class SimpleCommandLightOff : ICommand
{
private readonly Light light;
public SimpleCommandLightOff(Light light)
{
this.light = light;
}
public void Execute()
{
light.Off();
}
}
// Invoker
public class SimpleRemoteControl
{
private ICommand command;
public void SetCommand(ICommand command) {
this.command = command;
}
public void OnButtonPress() {
command.Execute();
}
// OffCommand needs to be set
public void OffButtonPress() {
command.Execute();
}
}
In the book they're stating that this is possible:
Light light = new Light();
remote.SetCommand(() => light.On());
However c# throws an error. Is this no the case when working with C#?
This does not work because in C#, lambda expressions map to delegates - a concept that does not exist in Java. Java has had a lot of these one-method interfaces for a long time before they finally introduced lambdas in Java 8. Given this and the lack of delegates, it was more or less natural to associate lambdas wit these one-method interfaces. C# / .NET, on the other hand, had delegates from the beginning and used them at many places where you would find a one-method interface in Java. Compare e.g. Observer and EventHandler.
So in a .NET API, you would consider using a delegate type like Action instead of ICommand, and then you would be able to use a lambda with it.
It should also be noted that .NET does have one-method interfaces, too. Some basic guidance about when to choose an interface or a delegate can be found at MSDN.
Matthias' answer is great, let me just add how a C# idiomatic way of declaring a command would look like:
delegate void Command();
That's it (though nowadays, you'd just use the generic Action delegate rather than defining your own). Your method would be
public void SetCommand(Command command)
{
this.command = command;
}
and invoking the command is as simple as
command();
Calling the SetCommand method can look like this:
SetCommand(() => DoSomething()); // Lambda
SetCommand(delegate () { DoSomething(); }); // Anonymous method
SetCommand(Someone.DoSomething); // Named method - Someone can be a type or an instance
As you can see, there's little point in using an interface for something a simple delegate can do. Java uses the syntax it does because it never supported delegates, and because it supports anonymous interface implementations - something C# doesn't have.
As an added bonus, delegates natively support chains - so a delegate can represent a set of delegates that are to be executed in a sequence. This is mostly used in events - another syntax helper that makes your job a little bit easier, with the handy syntax of SomeEvent += someDelegate; to register an event handler.
As an alternative, one can create an implementation of the interface that passes the calls through to lambda expressions.
public interface ICommand
{
void Execute();
int Calculate(int input);
}
public class LambdaCommand : ICommand
{
readonly Action execute;
readonly Func<int, int> calculate;
public LambdaCommand(Action execute, Func<int, int> calculate)
{
this.execute = execute;
this.calculate = calculate;
}
public void Execute() => execute();
public int Calculate() => calculate();
}
...
remote.SetCommand(new LambdaCommand(() => light.On(), _ => _));

Simple Injector usage for generic command handler

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);

Reactive Extensions: Allowing only a single subscriber for each type

Is there a way to ensure that there can be at most one subscriber registered per type for a generic type? An example would explain it better:
public interface Message
{
}
public class Command : Message
{
}
public class Event : Message
{
}
public class Bus
{
private readonly IObservable<Message> _stream;
private readonly Subject<Message> _subject;
public Bus()
{
_subject = new Subject<Message>();
_stream = _subject.AsObservable();
}
public IDisposable Subscribe<T>(IObserver<T> observer) where T:Command
{
return _stream.OfType<T>().Subscribe(observer);
}
public void Execute<T>(T command) where T:Command
{
_subject.OnNext(command);
}
}
I'd like to ensure that more than one observer cannot subscribe to the same type of Command. Is there something in Rx that allows that, or am I limited to:
a) Keep a lookup of types myself or
b) Not deal with it during registration, and use an interim subscriber to detect multiple registrations?
I do not think that Rx provides any built in mechanisms for this. Given your example code, I'd just make a Dictionary<Type, IObserver<T>> and use it within your Subscribe method to enforce your constraint.

How to define a new class that inherits from Delegate

is there anyway to do something similar to what ive got bellow.
What im trying to do is to invoke a list of delegates at a specific point in time and keep track of them, and for the sake of keeping code clean, keep the delegates to be invoked in a list of some sort.
public interface IServiceStatusDelegate
{
object DynamicInvoke(object[] args)
}
public class ServiceStatusDelegate
: Delegate, IServiceStatusDelegate
{
}
public class MyServiceStatusCheckedDelegate
: ServiceStatusDelgate
{
}
public class MyServiceStatusChangedDelegate
: ServiceStatusDelgate
{
}
public class MyClass
{
public ServiceStatusDelgate[] listOfDelegatesToInvoke;
public void InvokeRequiredDelegates()
{
foreach(ServiceStatusDelegate delegateToInvoke in this.listOfDelegatesToInvoke)
delegateToInvoke.DynamicInvoke(new object[]{this, DateTime.Now});
}
}
You don't need a list of delegates... any delegate you create in c# is going to be multicast, so all you need is any delegate, and you can combine them with +. Just invoke it and all targets will be reached. For example:
Action target = null;
...
target += Method1;
...
target += Method2;
...
if(target != null) target(); // calls Method1 and Method2
This could (although it isn't necessary for it to stand) be implemented via an event which will make the convention very obvious the caller.

Categories

Resources