public function load($ident, $metadata = [], array $idents = null)
    {
        if (!is_string($ident)) {
            throw new InvalidArgumentException(sprintf(
                'Metadata identifier must be a string, received %s',
                is_object($ident) ? get_class($ident) : gettype($ident)
            ));
        }

        if (strpos($ident, '\\') !== false) {
            $ident = $this->metaKeyFromClassName($ident);
        }

        $valid = $this->validateMetadataContainer($metadata, $metadataType, $targetMetadata);
        if ($valid === false) {
            throw new InvalidArgumentException(sprintf(
                'Metadata object must be a class name or instance of %s, received %s',
                MetadataInterface::class,
                is_object($metadata) ? get_class($metadata) : gettype($metadata)
            ));
        }

        if (isset(static::$metadataCache[$ident])) {
            $cachedMetadata = static::$metadataCache[$ident];

            if (is_object($targetMetadata)) {
                return $targetMetadata->merge($cachedMetadata);
            } elseif (is_array($targetMetadata)) {
                return array_replace_recursive($targetMetadata, $cachedMetadata->data());
            }

            return $cachedMetadata;
        }

        $data = $this->loadMetadataFromCache($ident, $idents);

        if (is_object($targetMetadata)) {
            return $targetMetadata->merge($data);
        } elseif (is_array($targetMetadata)) {
            return array_replace_recursive($targetMetadata, $data);
        }

        $targetMetadata = new $metadataType;
        $targetMetadata->setData($data);

        static::$metadataCache[$ident] = $targetMetadata;

        return $targetMetadata;
    }