public function getView($name = null, $format = 'html', $engine = null, $forceNew = false)
    {
        $name = $name ?: $this->getName();

        $format = $format ?: 'html';

        $key = ViewResolver::getDIKey($name . '.' . strtolower($format));

        // Let's prepare controller getter.
        if (!$this->container->exists($key)) {
            $this->container->share($key, function (Container $container) use ($name, $format, $engine) {
                // Find if package exists
                $viewName = sprintf('%s\%s%sView', ucfirst($name), ucfirst($name), ucfirst($format));

                $config = clone $this->config;

                /*
                 * If the name of this view not same as this controller, we don't pass name into it,
                 * so that the view will keep it's own name.
                 * Otherwise we override the name in view config with ours.
                 */
                if ($name && strcasecmp($name, $this->getName()) !== 0) {
                    $config['name'] = null;
                }

                try {
                    // Use MvcResolver to find view class.
                    $class = $this->getPackage()->getMvcResolver()->getViewResolver()->resolve($viewName);

                    // Create object by container, container will auto inject all necessary dependencies
                    return $container->createSharedObject($class, ['renderer' => $engine, 'config' => $config]);
                } catch (\Exception $e) {
                    if (!$e instanceof \DomainException && !$e instanceof \UnexpectedValueException) {
                        throw $e;
                    }

                    // Guess the view position
                    $class = MvcHelper::getPackageNamespace($this) . '\View\\' . ucfirst($viewName);

                    if (class_exists($class)) {
                        return $container->createSharedObject($class, ['renderer' => $engine, 'config' => $config]);
                    }

                    // If format is html or NULL, we return HtmlView as default.
                    if (strtolower($format) === 'html') {
                        $config['name'] = $name;

                        return new HtmlView([], $config, $engine);
                    }

                    // Otherwise we throw exception to notice developers that they did something wrong.
                    throw $e;
                }
            });
        }

        // Get view from controller.
        return $this->container->get($key, $forceNew);
    }