多重依赖
多重依赖:不是”死循环“依赖,而是在解析时需要多重解析。
例如: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']));
输出:
小结
1、多重依赖解析,主要是依赖递归不断解析依赖类所依赖的其它类。
2、PHP对反射的支持非常强大,许多依赖注入的框架基本都支持反射对类的解析。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。