diff --git a/CHANGELOG.md b/CHANGELOG.md index 31be3972..e361ce4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - **Experimental** Fundefs whose function is annotated with `@Fundef` can now be `put()` like any other component, e.g. `put(::myFundef)` ([#87](https://github.com/utybo/Tegral/pull/87)) + - Factories now support qualifiers. Add the qualifier to the `putFactory` call and use it when requesting a factory like with a regular component. + ## [0.0.4] - 2023-05-14 ### Added diff --git a/docs/docs/modules/core/di/extensions/factories.md b/docs/docs/modules/core/di/extensions/factories.md index 351ad2fb..7eb9612f 100644 --- a/docs/docs/modules/core/di/extensions/factories.md +++ b/docs/docs/modules/core/di/extensions/factories.md @@ -33,6 +33,18 @@ class INeedBar(scope: InjectionScope) { } ``` +You can also add qualifiers to factories, similarly to regular components: + +```kotlin +val myEnvironment = tegralDi { + putFactory(named("BAR!")) { Bar() } +} + +class INeedBar(scope: InjectionScope) { + val bar: Bar by scope(named("BAR!")) +} +``` + Here is a full example using loggers: ```kotlin diff --git a/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/environment/resolvers/AliasIdentifierResolver.kt b/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/environment/resolvers/AliasIdentifierResolver.kt index c84cac46..b19072d2 100644 --- a/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/environment/resolvers/AliasIdentifierResolver.kt +++ b/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/environment/resolvers/AliasIdentifierResolver.kt @@ -20,7 +20,7 @@ import guru.zoroark.tegral.di.environment.Identifier import guru.zoroark.tegral.di.environment.ensureInstance /** - * A resolver that is aliased to another identifier. Not canonical. + * A resolver that is aliased to another resolver. Not canonical. */ class AliasIdentifierResolver(private val actualIdentifier: Identifier) : IdentifierResolver { override val requirements: List> = listOf(actualIdentifier) diff --git a/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/environment/resolvers/IdentifierResolver.kt b/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/environment/resolvers/IdentifierResolver.kt index db2e1ecc..a7293dd4 100644 --- a/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/environment/resolvers/IdentifierResolver.kt +++ b/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/environment/resolvers/IdentifierResolver.kt @@ -18,9 +18,15 @@ import guru.zoroark.tegral.di.environment.EnvironmentComponents import guru.zoroark.tegral.di.environment.Identifier /** - * A resolver is an object that helps resolve an identifier into an actual component. + * A resolver is an object that resolves an identifier into an actual component. * - * The implementation dictates how such a component is retrieved, created, etc. + * The implementation dictates how such a component is retrieved, created, etc. Resolvers have access to all components + * available in the environment, and can use any component they require to resolve the identifier. Resolvers are an + * intermediary step between the user (or some component) asking for a component, and the retrieval of that component in + * the environment. + * + * The most commonly used implementation of this is [SimpleIdentifierResolver], that simply retrieves the corresponding + * component in the environment. For an examples of a more advanced resolver, see [AliasIdentifierResolver] */ interface IdentifierResolver { /** diff --git a/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/extensions/factory/InjectableFactory.kt b/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/extensions/factory/InjectableFactory.kt index 59a314b4..a7c1cbee 100644 --- a/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/extensions/factory/InjectableFactory.kt +++ b/tegral-di/tegral-di-core/src/main/kotlin/guru/zoroark/tegral/di/extensions/factory/InjectableFactory.kt @@ -18,11 +18,14 @@ import guru.zoroark.tegral.core.TegralDsl import guru.zoroark.tegral.di.InvalidDeclarationException import guru.zoroark.tegral.di.dsl.ContextBuilderDsl import guru.zoroark.tegral.di.dsl.put +import guru.zoroark.tegral.di.environment.EmptyQualifier import guru.zoroark.tegral.di.environment.EnvironmentComponents import guru.zoroark.tegral.di.environment.Identifier import guru.zoroark.tegral.di.environment.InjectionScope +import guru.zoroark.tegral.di.environment.Qualifier import guru.zoroark.tegral.di.environment.ResolvableDeclaration import guru.zoroark.tegral.di.environment.invoke +import guru.zoroark.tegral.di.environment.plus import guru.zoroark.tegral.di.environment.resolvers.IdentifierResolver import guru.zoroark.tegral.di.environment.typed import kotlin.properties.ReadOnlyProperty @@ -90,13 +93,13 @@ class FactoryDeclaration( * services (also known as a singleton), factories */ @TegralDsl -inline fun ContextBuilderDsl.putFactory(noinline block: (Any) -> T) { - put>(typed()) { InjectableFactoryImpl(block) } +inline fun ContextBuilderDsl.putFactory(qualifier: Qualifier = EmptyQualifier, noinline block: (Any) -> T) { + put>(typed() + qualifier) { InjectableFactoryImpl(block) } @Suppress("UNCHECKED_CAST") put( FactoryDeclaration( - Identifier(T::class), - Identifier(InjectableFactory::class as KClass>, typed()) + Identifier(T::class, qualifier), + Identifier(InjectableFactory::class as KClass>, typed() + qualifier) ) ) } diff --git a/tegral-di/tegral-di-core/src/test/kotlin/guru/zoroark/tegral/di/extensions/FactoryExtensionTest.kt b/tegral-di/tegral-di-core/src/test/kotlin/guru/zoroark/tegral/di/extensions/FactoryExtensionTest.kt index 113a96dc..f8be9b43 100644 --- a/tegral-di/tegral-di-core/src/test/kotlin/guru/zoroark/tegral/di/extensions/FactoryExtensionTest.kt +++ b/tegral-di/tegral-di-core/src/test/kotlin/guru/zoroark/tegral/di/extensions/FactoryExtensionTest.kt @@ -24,6 +24,7 @@ import guru.zoroark.tegral.di.environment.InjectionScope import guru.zoroark.tegral.di.environment.MixedImmutableEnvironment import guru.zoroark.tegral.di.environment.get import guru.zoroark.tegral.di.environment.invoke +import guru.zoroark.tegral.di.environment.named import guru.zoroark.tegral.di.extensions.factory.factory import guru.zoroark.tegral.di.extensions.factory.putFactory import io.mockk.mockk @@ -216,4 +217,22 @@ class FactoryExtensionTest { } assertEquals("I am AAA's A", env.get().a.identity) } + + class ABUser(scope: InjectionScope) { + val factoryA: A by scope() + val factoryB: A by scope(named("BBB")) + } + + @Test + fun `Putting a factory with a qualifier`() { + val env = tegralDi { + putFactory { A("AAA") } + putFactory(named("BBB")) { A("BBB") } + put(::ABUser) + } + val abUser = env.get() + assertEquals("I am AAA's A", abUser.factoryA.identity) + assertEquals("I am BBB's A", abUser.factoryB.identity) + + } }