多重依赖

多重依赖:不是”死循环“依赖,而是在解析时需要多重解析。
例如:C依赖B-》B依赖A-》A依赖...

几个方法说明

ReflectionParameter::getClass():获取参数类,返回的ReflectionClass对象。
ReflectionParameter::getName():获取参数名,不仅仅包括对象类型参数,还包括普通参数参数名的获取。
ReflectionClass::getName():获取类名。

多重依赖解析代码

主要用到了ReflectionClass、ReflectionMethod和ReflectionParameter
增加了支持普通参数解析,并支持默认参数解析
/**
 * 多重依赖解析
 */
function make($abstract, $parameters=[]) {
    if ($abstract instanceof \Closure) {
        return $abstract($parameters);
    }

    $resolveParams = resolveParamContext($abstract, $parameters);
    return (new ReflectionClass($abstract))->newInstanceArgs($resolveParams);
}

function resolveParamContext($abstract, $parameters = []) {
    $reflector = new ReflectionClass($abstract);

    $resolveParams = [];
    if ($reflectorMethod = $reflector->getMethod("__construct")) {
        $reflectorParameters = $reflectorMethod->getParameters();
        foreach ($reflectorParameters as $parameter) {
            if (array_key_exists($parameter->getName(), $parameters)) {
                if (!empty($parameters[$parameter->getName()])) {
                    $resolveParams[] = $parameters[$parameter->getName()];
                    continue;
                } else if ($parameter->isDefaultValueAvailable()){
                    $resolveParams[] = $parameter->getDefaultValue();
                } else {
                    throw new \Exception("parameter ".$parameter->getName()." none given");
                }
            }

            // 对象类型多重依赖解析
            if ($class = $parameter->getClass()) {
                $className = $class->getName();
                $resolveParams[] = (new ReflectionClass($className))
                    ->newInstanceArgs(resolveParamContext($className, $parameters));
            }
        }
    }

    return $resolveParams;
}
/**
 * 测试反射多重依赖解析
 * 例如:
 * 解析实例C,C依赖B,B又依赖A
 */
class A {
    public function __construct()
    {
        echo "A\n";
    }
}

class B {
    public $a = null;
    public function __construct(A $a)
    {
        $this->a = $a;
    }
}

class C {
    public $b = null;
    public $c = null;
    public $default = null;
    public function __construct(B $b, $c, $default='default')
    {
        $this->b = $b;
        $this->c = $c;
        $this->default = $default;
    }
}

var_dump(make('C', ['c' => 'c_param']));

输出:
image.png

小结

1、多重依赖解析,主要是依赖递归不断解析依赖类所依赖的其它类。
2、PHP对反射的支持非常强大,许多依赖注入的框架基本都支持反射对类的解析。

hiyanxu
4 声望1 粉丝