public function resolve(string $expression, $callable, array $aliases = []): StringCommand
    {
        $this->assertCallableIsValid($callable);

        $commandFunction = function (InputInterface $input, OutputInterface $output) use ($callable) {
            $parameters = \array_merge(
                [
                    // Injection by parameter name
                    'input'  => $input,
                    'output' => $output,
                    // Injections by type-hint
                    InputInterface::class  => $input,
                    OutputInterface::class => $output,
                    Input::class           => $input,
                    Output::class          => $output,
                    SymfonyStyle::class    => new SymfonyStyle($input, $output),
                ],
                $input->getArguments(),
                $input->getOptions()
            );

            if ($callable instanceof Closure) {
                $callable = $callable->bindTo($this->console, $this->console);
            }

            try {
                return $this->invoker->addResolver(new HyphenatedInputResolver())->call($callable, $parameters);
            } catch (InvokerInvocationException $exception) {
                throw new InvocationException(
                    \sprintf(
                        "Impossible to call the '%s' command: %s",
                        $input->getFirstArgument(),
                        $exception->getMessage()
                    ),
                    0,
                    $exception
                );
            }
        };

        $command = self::createCommand($expression, $commandFunction);
        $command->setAliases($aliases);
        $command->defaults($this->defaultsViaReflection($command, $callable));

        return $command;
    }