From 5a9fa793dff9c3bfc0a8deacce5a30a8cd8c4794 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Tue, 16 Jul 2024 22:15:29 +0200 Subject: [PATCH] Add Injector::implementations() to select implementations for a given type --- src/main/php/inject/Implementations.class.php | 46 +++++++++++++++++++ src/main/php/inject/Injector.class.php | 16 +++++++ .../unittest/ImplementationsTest.class.php | 46 +++++++++++++++++++ .../unittest/fixture/Creation.class.php | 3 ++ .../php/inject/unittest/fixture/URI.class.php | 5 +- 5 files changed, 115 insertions(+), 1 deletion(-) create mode 100755 src/main/php/inject/Implementations.class.php create mode 100755 src/test/php/inject/unittest/ImplementationsTest.class.php diff --git a/src/main/php/inject/Implementations.class.php b/src/main/php/inject/Implementations.class.php new file mode 100755 index 0000000..26426e2 --- /dev/null +++ b/src/main/php/inject/Implementations.class.php @@ -0,0 +1,46 @@ +inject= $inject; + $this->bindings= $bindings; + } + + /** + * Returns the default implementation + * + * @return T + */ + #[Generic(return: 'T')] + public function default() { + return current($this->bindings)->resolve($this->inject); + } + + /** + * Returns the implementation for a given name + * + * @param string $name + * @return T + * @throws inject.ProvisionException if there is no such implementation + */ + #[Generic(return: 'T')] + public function named($name) { + if ($binding= $this->bindings[$name] ?? null) { + return $binding->resolve($this->inject); + } + + throw new ProvisionException('No implementation named "'.$name.'"'); + } +} \ No newline at end of file diff --git a/src/main/php/inject/Injector.class.php b/src/main/php/inject/Injector.class.php index 7959505..36b4ac9 100755 --- a/src/main/php/inject/Injector.class.php +++ b/src/main/php/inject/Injector.class.php @@ -89,6 +89,22 @@ public function bind($type, $impl, $name= null) { return $this; } + /** + * Returns implementations for a given type + * + * @param string|lang.Type $type + * @return inject.Implementations + * @throws inject.ProvisionException + */ + public function implementations($type) { + $t= $type instanceof Type ? $type : Type::forName($type); + if ($bindings= $this->bindings[$t->literal()] ?? null) { + return new Implementations($this, $bindings); + } + + throw new ProvisionException('No implementations for type '.$t); + } + /** * Returns the lookup if it provides a value, null otherwise * diff --git a/src/test/php/inject/unittest/ImplementationsTest.class.php b/src/test/php/inject/unittest/ImplementationsTest.class.php new file mode 100755 index 0000000..99dc81f --- /dev/null +++ b/src/test/php/inject/unittest/ImplementationsTest.class.php @@ -0,0 +1,46 @@ +uris= [ + 'dev' => new URI('http://localhost'), + 'prod' => new URI('https://example.com'), + ]; + } + + /** @return inject.Injector */ + private function fixture() { + $fixture= new Injector(); + foreach ($this->uris as $name => $uri) { + $fixture->bind(URI::class, $uri, $name); + } + return $fixture; + } + + #[Test, Values(['dev', 'prod'])] + public function implementations_named($name) { + Assert::equals($this->uris[$name], $this->fixture()->implementations(URI::class)->named($name)); + } + + #[Test] + public function default_implementation() { + Assert::equals($this->uris['dev'], $this->fixture()->implementations(URI::class)->default()); + } + + #[Test, Expect(ProvisionException::class)] + public function no_implementations() { + $this->fixture()->implementations(Endpoint::class); + } + + #[Test, Expect(ProvisionException::class)] + public function unknown_implementation() { + $this->fixture()->implementations(URI::class)->named('stage'); + } +} \ No newline at end of file diff --git a/src/test/php/inject/unittest/fixture/Creation.class.php b/src/test/php/inject/unittest/fixture/Creation.class.php index c7771e7..2ae11e9 100755 --- a/src/test/php/inject/unittest/fixture/Creation.class.php +++ b/src/test/php/inject/unittest/fixture/Creation.class.php @@ -4,4 +4,7 @@ class Creation { /** Create fluent interface for URIs */ public function __construct(URI $uri) { /* ... */ } + + /** @return string */ + public function create() { /* ... */ } } \ No newline at end of file diff --git a/src/test/php/inject/unittest/fixture/URI.class.php b/src/test/php/inject/unittest/fixture/URI.class.php index fd782a0..9d3f6e5 100755 --- a/src/test/php/inject/unittest/fixture/URI.class.php +++ b/src/test/php/inject/unittest/fixture/URI.class.php @@ -1,7 +1,10 @@ backing= $arg instanceof Creation ? $arg->create() : (string)$arg; + } } \ No newline at end of file