public function getInstance(string $class, string $selector = Injector::DEFAULT_SELECTOR)
    {
        if (array_search($class, $this->instance_stack, true))
            throw new DIException("Cyclic dependencies in creating $class: " . WF::str($this->instance_stack));

        array_push($this->instance_stack, $class);
        try
        {
            if (!isset($this->objects[$class]) || !isset($this->objects[$class][$selector]))
            {
                if ($selector === Injector::SHARED_SELECTOR)
                    throw new DIException("Refusing to instantiate shared instance");

                if (isset($this->objects[$class][Injector::SHARED_SELECTOR]))
                {
                    $instance = $this->objects[$class][Injector::SHARED_SELECTOR];
                }
                else
                {
                    $instance = $this->newInstance($class, ['wdiSelector' => $selector]);
                    $nclass = get_class($instance);
                    $const_name = $nclass . '::WDI_REUSABLE';
                    if (defined($const_name) && constant($const_name) === true)
                        $this->setInstance($class, $instance, $selector);
                }
            }
            else
            {
                $instance = $this->objects[$class][$selector];
            }
        }
        finally
        {
            $top = array_pop($this->instance_stack);
            if ($class !== $top)
            {
                // @codeCoverageIgnoreStart
                throw new DIException("Unexpected class at top of stack: expected $class, found $top");
                // @codeCoverageIgnoreEnd
            }
        }

        return $instance;
    }