php设计模式-简单依赖注入容器+自动绑定特性

class C
{
    public function sayHello()
    {
        echo 'I am C';
    }
}

class B
{
    private $_c;

    public function __construct(C $c)
    {
        $this->_c = $c;
    }

    public function sayHello()
    {
        echo 'I am B';
        $this->_c->sayHello();
    }
}

class A
{
    private $_b;

    public function __construct(B $b)
    {
        $this->_b = $b;
    }

    public function sayHello()
    {
        echo 'I am A';
        $this->_b->sayHello();
    }
}

echo '<pre>';

class Container
{
    private $_map = array();

    public function __set($k, $c)
    {
        $this->_map[$k] = $c;
    }

    public function __get($k)
    {
        if (!isset($this->_map[$k])) throw new Exception('Undefined class');
        return $this->build($this->_map[$k]);
    }

    private function build($classname)
    {
        if ($classname instanceof Closure) return $classname($this);

        $reflection = new ReflectionClass($classname); // 涉及php反射相关知识

        // 检查类是否可实例化, 排除抽象类abstract和对象接口interface
        if (!$reflection->isInstantiable()) throw new Exception("接口不能被实例化");

        if ($reflection === null) throw new Exception('类未定义');

        $constructor = $reflection->getConstructor();
        
        if (is_null($constructor)) return new $classname;
        
        if (!$constructor->isPublic()) throw new Exception('类不能被实例化');

        $parameters = $constructor->getParameters();

        if ($parameters === null) return new $classname;

        // 递归解析构造参数
        $dependencies = $this->_getDependency($parameters);

        // 创建一个类的新实例,给出的参数将传递到类的构造函数。
        return $reflection->newInstanceArgs($dependencies);
    }

    private function _getDependency($parameters)
    {
        $dependencies = [];

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

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

        return $dependencies;
    }

    private function _resolveClass($parameter)
    {
        if ($parameter->isDefaultValueAvailable()) {
            return $parameter->getDefaultValue();
        }

        throw  new  Exception('Unknow error');
    }
}

$di = new Container();
$di->a = 'A';
$di->a->sayHello();

  结果:

I am AI am BI am C

  

posted @ 2020-07-22 22:14  coder_xds  阅读(178)  评论(0编辑  收藏  举报