Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Support Provider-like API for Instance Creation #457

Closed
leinardi opened this issue Dec 2, 2024 · 5 comments
Closed

Feature Request: Support Provider-like API for Instance Creation #457

leinardi opened this issue Dec 2, 2024 · 5 comments

Comments

@leinardi
Copy link

leinardi commented Dec 2, 2024

Use Provider<T> to enable flexible and explicit creation of new instances of a dependency directly within the injection target. This avoids boilerplate factory definitions in the component and allows injection targets to control when and how many instances of a dependency are created.

Currently, kotlin-inject supports creating new instances through factory methods in @Component but, as far as I know, there is no built-in equivalent for a Provider<T>-like API directly available in injection targets.


Proposed Solution

Introduce a Provider<T>-like interface into kotlin-inject that can be injected into classes. This would allow injection targets to request new instances of a dependency explicitly and on demand.

The proposed interface:

interface Provider<T> {
    fun get(): T
}

The kotlin-inject compiler would generate providers automatically for any class or dependency annotated with @Inject. The Provider<T> would invoke the binding logic for T each time get() is called.


Example: New Instance Creation in Injection Target

Here’s an example adapted to kotlin-inject:

Target Class
import me.tatarka.inject.annotations.Inject

@Inject
class BigCoffeeMaker(private val filterProvider: Provider<Filter>) {
    fun brew(numberOfPots: Int) {
        repeat(numberOfPots) {
            val filter = filterProvider.get() // New filter instance every time
            // Use the filter
        }
    }
}
Filter Class
@Inject
class Filter {
    // Implementation of Filter
}
AppComponent
@Component
abstract class AppComponent {
    abstract val bigCoffeeMaker: BigCoffeeMaker
}
Main Function
fun main() {
    val appComponent = AppComponent::class.create()
    val coffeeMaker = appComponent.bigCoffeeMaker
    coffeeMaker.brew(5)
}

Benefits

Eliminates the need for repetitive factory definitions in components or manual object creation in injection targets.

@leinardi
Copy link
Author

leinardi commented Dec 2, 2024

Mmm, maybe this feature request is not necessary, am I wrong or I can just create a new instance using a lambda?

class BigCoffeeMaker(private val filterProvider: () -> Filter) {
}

@evant
Copy link
Owner

evant commented Dec 2, 2024

Yes you can use a lambda

@leinardi
Copy link
Author

leinardi commented Dec 2, 2024

Nice, is this documented anywhere? I thought it was a missing feature because I couldn't find how to do it

@evant
Copy link
Owner

evant commented Dec 2, 2024

It's under https://github.com/evant/kotlin-inject?tab=readme-ov-file#function-support--assisted-injection

I do understand the documentation can be improved, feel free to add your feedback to #389

@leinardi
Copy link
Author

leinardi commented Dec 3, 2024

Sure, done: #389 (comment)

@leinardi leinardi closed this as completed Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants