依赖注入,控制反转容器(ioc)


class Container {
    protected $bindings = [];
    protected $resolved = [];
    protected $instances = [];

    public function make($className) {
        return $this->resolve($className);
    }

    public function singleton($className, Closure $resolver = null) {
        return $this->bind($className, $resolver, true);
    }

    public function bind($className, Closure $resolver = null, $shared = false) {
        if (is_null($resolver)) {
            $resolver = $className;
        }

        $this->bindings[$className] = compact('resolver', 'shared');

    }

    protected function resolve($className) {
        if (isset($this->instances[$className])) {
            return $this->instances[$className];
        }

        $concrete = $this->getConcrete($className);

        $object = $this->build($concrete);

        if ($this->isShared($className)) {
            $this->instances[$className] = $object;
        }

        $this->resolved[$className] = true;
        return $object;
    }

    protected function getConcrete($className) {
        if (isset($this->bindings[$className])) {
            return $this->bindings[$className]['resolver'];
        }

        return $className;
    }

    protected function build($concrete) {
        if ($concrete instanceof Closure) {
            return $concrete($this);
        }

        $reflector = new ReflectionClass($concrete);

        if (!$reflector->isInstantiable()) { 
            throw new Exception("Target [$concrete] is not instantiable.");
        }

        $constructor = $reflector->getConstructor();

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

        $parameters = $constructor->getParameters();

        $dependencies = $this->resolveDependencies($parameters);

        return $reflector->newInstanceArgs($dependencies);
    }

    protected function resolveDependencies($parameters) {
        $dependencies = [];

        foreach ($parameters as $parameter) {
            $dependency = $parameter->getClass();

            if (is_null($dependency)) {
                $dependencies[] = $this->resolveNonClass($parameter);
            } else {
                $dependencies[] = $this->build($dependency->getName());
            }
        }

        return $dependencies;
    }

    protected function resolveNonClass($parameter) {
        if ($parameter->isDefaultValueAvailable()) {
            return $parameter->getDefaultValue();
        }

        throw new Exception('I have no idea what to do here.');
    }

    protected function isShared($className) {
        return isset($this->instances[$className]) || 
               (isset($this->bindings[$className]['shared']) && 
                $this->bindings[$className]['shared'] === true);
    }

    public function __get($className) {
        return $this->make($className);
    }

}

class Test {
    private $ioc;

    public function __construct($ioc) {
        $ioc->bind('show', function ($ioc) {
            return "Test --> show";
        });
        $this->ioc = $ioc;
    }

    public function show() {
        return $this->ioc->show;
    }
}

class Foo {

    private $bim;

    public function __construct(Bim $bim) {
        $this->bim = $bim;
    }
}

class Bar {

}

class Bim {
    private $bar;

    public function __construct(Bar $bar) {
        $this->bar = $bar;
    }
}

$Ioc = new Container();

$Ioc->singleton('Foo');

$bim = $Ioc->make('Foo');
var_dump($bim);

$Ioc->bind('Test', function ($ioc) {
    return new Test($ioc);
});

echo $Ioc->Test->show();

你可能感兴趣的:(依赖注入,控制反转容器(ioc))