Kontravarianz? Kovarianz? Was ist los mit dieser generischen Architektur ...?

Ich habe einige Probleme beim Einrichten einer Befehlsverarbeitungsarchitektur. Ich möchte in der Lage sein, eine Reihe verschiedener Befehle zu erstellen, die von ICommand abgeleitet sind. Erstellen Sie dann eine Reihe verschiedener Befehlshandler, die von ICommandHandler abgeleitet sind.

Hier ist das Interface und die Klassen, mit deren Definition ich begonnen habe:

interface ICommand {}

class CreateItemCommand : ICommand {}

interface ICommandHandler<TCommand> where TCommand : ICommand {
    void Handle(TCommand command);
}

class CreateItemCommandHandler : ICommandHandler<CreateItemCommand> {
    public void Handle(CreateItemCommand command) {
        // Handle the command here
    }
}

Ich habe eine Hilfsklasse, die den entsprechenden Befehlstyp erstellen kann:

class CommandResolver {
    ICommand GetCommand(Message message) {
        return new CreateItemCommand(); // Handle other commands here
    }
}

Und eine Helferklasse, die den entsprechenden Handler erstellt. Hier habe ich Probleme:

class CommandHandlerResolver {
    public ICommandHandler<TCommand> GetHandler<TCommand>(TCommand command) {

        // I'm using Ninject and have an instance of an IKernel 
        // The following code throws an exception despite having a proper binding
        //    _kernel.GetService(typeof(ICommandHandler<TCommand>))

        var bindingType = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
        var handler = _kernel.GetService(bindingType);
        return handler as ICommandHandler<TCommand>; 
        // handler will be null after the cast
    }
}

Hier ist die Hauptausführungsmethode

CommandResolver _commandResolver;
HandlerResolver _handlerResolver;

void Run() {

    // message is taken from a queue of messages    

    var command = _commandResolver.GetCommand(message);

    var handler = _handlerResolver.GetHandler(command);
    // handler will always be null

    handler.Handle(command);
}

Ich kann mir verschiedene Möglichkeiten vorstellen, den Code zu überarbeiten, um das Problem sicher zu vermeiden, aber ich war ein bisschen ratlos über das Problem und wollte mehr darüber wissen, was vor sich geht.

Dieser Entwurf sieht aus wie es funktionieren sollte.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage