public function handle(array $args = [])
    {
        // remove source file name from argv
        $source = array_shift($args);

        /** @var ConsoleEvent $applicationEvent */
        $applicationEvent = $this->getApplicationEvent();
        $applicationEvent->setName(self::EVENT_REQUEST_RECEIVED);
        $applicationEvent->setSourceFile($source);
        $applicationEvent->setArguments($args);
        $this->emit($applicationEvent);

        // init dispatcher
        $dispatcher = new Dispatcher($this->commands, $this->container);

        $middlewareRunner = new MiddlewareRunner($this->getMiddlewares());

        $middlewareRunner->run([$applicationEvent->getArguments()], function ($args) use ($applicationEvent, $dispatcher) {
            // dispatch command with args from cli
            $dispatcher->dispatch($args);
        });
    }