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)
最新推荐文章于 2024-07-10 15:47:00 发布