protected function build($concrete, array $arguments = [])
    {
        if (is_callable($concrete)) {
            return $concrete($this, $arguments);
        }

        if (isset($this->reflectionClass[$concrete])) {
            $reflection = $this->reflectionClass[$concrete];
        } else {
            try {
                $reflection = $this->reflectionClass[$concrete] = new ReflectionClass($concrete);
            } catch (\ReflectionException $e) {
                throw new BindingException('ReflectionException: ' . $e->getMessage());
            }
        }

        if (!$reflection->isInstantiable()) {
            throw new BindingException("The '${concrete}' type is not instantiable");
        }

        if (isset($this->reflectionMethod[$concrete])) {
            $constructor = $this->reflectionMethod[$concrete];
        } else {
            $constructor = $this->reflectionMethod[$concrete] = $reflection->getConstructor();
        }

        if (is_null($constructor)) {
            return new $concrete();
        }

        // Resolve arguments
        $parameters = array_diff_key($constructor->getParameters(), $arguments);

        /**
         * @var int $key
         * @var  \ReflectionParameter $parameter
         */
        foreach ($parameters as $key => $parameter) {
            if (null === $class = $parameter->getClass()) {
                if ($parameter->isDefaultValueAvailable()) {
                    $arguments[$key] = $parameter->getDefaultValue();
                } else {
                    throw new BindingException("Could not resolve [$parameter]");
                }
                continue;
            }

            try {
                $class = $class->name;
                $arguments[$key] = isset($this->bindings[$class]) ? $this->make($class) : $this->build($class);
            } catch (BindingException $e) {
                if (!$parameter->isOptional()) {
                    throw $e;
                }
                $arguments[$key] = $parameter->getDefaultValue();
            }
        }

        ksort($arguments);

        return $reflection->newInstanceArgs($arguments);
    }