PHP:
class Injector {
protected $registry = [];
public function reuse(Closure $ctor) {
return function($self) use ($ctor) {
static $instance = null;
return null === $instance ? $instance = $ctor($self) : $instance;
};
}
public function setClosure($name, Closure $value) {
$this->$name = function() use ($value) {
return $value;
};
}
public function __set($name, $value) {
$this->registry[$name] = $value;
}
public function __get($name) {
if (!array_key_exists($name, $this->registry)) {
throw new InvalidArgumentException("Undefined dependency: '$name'");
}
return $this->registry[$name] instanceof Closure ? $this->registry[$name]($this) : $this->registry[$name];
}
}
PHP:
class InjectorTest extends PHPUnit_Framework_TestCase {
public function testObjectDependency() {
$inj = new Injector;
$inj->dep = function() {
return new stdClass;
};
$this->assertInstanceOf('stdClass', $inj->dep);
}
public function testValueDependency() {
$inj = new Injector;
$inj->dep = 'test';
$this->assertEquals('test', $inj->dep);
}
public function testInstancesAreDifferent() {
$inj = new Injector;
$inj->dep = function() {
return new stdClass;
};
$this->assertNotSame($inj->dep, $inj->dep);
}
public function testReusedInstancesAreSame() {
$inj = new Injector;
$inj->dep = $inj->reuse(function() {
return new stdClass;
});
$this->assertSame($inj->dep, $inj->dep);
}
public function testUsingArguments() {
$inj = new Injector;
$inj->flag = 1;
$inj->dependency = function() {
return new Dependency;
};
$inj->service = function($inj) {
return new Service($inj->dependency, $inj->flag);
};
$service = $inj->service;
$this->assertInstanceOf('Service', $service);
$this->assertInstanceOf('Dependency', $service->dependency);
$this->assertEquals(1, $service->flag);
}
public function testClosureDependency() {
$inj = new Injector;
$closure = function() { return true; };
$inj->setClosure('closure', $closure);
$this->assertInstanceOf('Closure', $inj->closure);
$this->assertTrue($inj->closure->__invoke());
}
}
class Dependency {}
class Service {
public function __construct(Dependency $dependency, $flag) {
$this->dependency = $dependency;
$this->flag = $flag;
}
}

Вполне юзабельно кстати, не true DI конечно, но зато безо всяких там тормозных reflection.