依赖注入,控制反转容器(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();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值