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

Forwarding parameters #66

Closed
Bodo1981 opened this issue Mar 2, 2018 · 8 comments
Closed

Forwarding parameters #66

Bodo1981 opened this issue Mar 2, 2018 · 8 comments
Milestone

Comments

@Bodo1981
Copy link

Bodo1981 commented Mar 2, 2018

Koin 0.9.0 is really great
Thanks for the parameter support when injecting dependencies. It is working great.

I have a small optimization for injecting with parameters.
It would be fantastic if we can forward this parameter map.

e.g.

class MyActivity : Activity() {
   val presenter: MyPresenter by inject(parameters = mapOf("activity" to this)
}

class MyPresenter(navigator: Navigator) {

}

class Navigator(activity: Activity) {

}

and the module looks like this

val myModule: Module = applicationContext {
   context("Screen") {
      bean { params -> MyPresenter(get()) }  // here we have the params with the activity 
      bean { params -> Navigator(params["activity"]) }  // BUT the activity is needed here (and here are params null)
   }
}

can you provide us with the possibillty to forward these params in the get() method, e.g

val myModule: Module = applicationContext {
   context("Screen") {
      bean { params -> MyPresenter(get(params)) }  // forward params in get(params)
      bean { params -> Navigator(params["activity"]) }  // so we can access the params here
   }
}

looking at the get() functions it should be possible
in the current version 0.9.0 you pass an emptyMap to the resolve functions.

inline fun <reified T : Any> get(): T = koinContext.resolveByClass(emptyMap())
inline fun <reified T : Any> get(name: String): T = koinContext.resolveByName(name, emptyMap())

maybe we can do something like this:

inline fun <reified T : Any> get(parameters: ParameterMap = emptyMap()): T = koinContext.resolveByClass(parameters)
inline fun <reified T : Any> get(name: String, parameters: ParameterMap = emptyMap()): T = koinContext.resolveByName(name, parameters)

What do you think about this?

@arnaudgiuliani
Copy link
Member

Hello,

I will allow propagating parameters in next patch. You will be able to use params.value to pass in your get()DSL function.

like:

//with classes
class ComponentA(val componentC: ComponentC)
class ComponentB(val componentA: ComponentA)
 val simpleModule1 = applicationContext {
        bean { params -> ComponentA(params["this"]) }
        bean { params -> ComponentB(get(parameters = params.values)) }
    }
     
   // injecting ...
val componentB: ComponentB by inject(parameters = mapOf("this" to this))

@leonardoaramaki
Copy link

leonardoaramaki commented Jun 10, 2018

@arnaudgiuliani How does this solves the OP's issue? I mean, in your example:
val componentB: ComponentB by inject(parameters = mapOf("this" to this))

But in the Navigator class of the OP's example, it needs an activity so inside it's not possible to inject the activity from there because in mapOf("this" to this)), this is not an Activity but instead a Navigator. Did I miss something?

@arnaudgiuliani
Copy link
Member

val componentB: ComponentB by inject(parameters = mapOf("this" to this))

means that you will store this with the key of "this". Which mean that you can reuse the value with this key in a definition: bean { parms -> ... params["this"] ... }

if your definition is using a compatible type of the forwarded parameter, it will be ok.

Did I respond to your question?

@jhandguy
Copy link

jhandguy commented Jul 6, 2018

Hey @arnaudgiuliani!
get(parameters = params.values) does not work for me, I get a type mismatch Parameters wanted and got Map<String, Any>, any idea?

@jhandguy
Copy link

jhandguy commented Jul 6, 2018

Got it!
Parameters is a typealias for () -> Map<String, Any> and not Map<String, Any>.
So the solution is to do get { it.values } =)

@arnaudgiuliani
Copy link
Member

yeah, it's a lambda. This can be a bit tricky.

@z3ntu
Copy link

z3ntu commented Dec 20, 2018

Hello. (while waiting for my kotlin slack invitation I'm writing here)

I have the following module defined:

val nextNewsModule = module {
    single { (acc: SingleSignOnAccount) -> provideAuthenticationInterceptor(acc) }
    single { params -> provideHttpClient(get { params }) }
    single { (acc: SingleSignOnAccount) -> provideRetrofit(get { params }, acc) }
    single { params -> provideNewsService(get { params }) }
    single<NewsRepository> { params -> NewsRepositoryImpl(get { params }) }
    viewModel { params -> NewsViewModel(get { params }) }
}

and getting called by

private val vm: NewsViewModel by viewModel { parametersOf(SingleSignOnAccount("a", "b", "c", "d")) }

The problem before adding all the params -> was that the "downstream dependencies" didn't get the required SingleSignOnAccount instance and Koin failed to inject.
Now I think I just need to pass the params object through the provideRetrofit line (so it reaches the provideAuthenticationInterceptor) but with the extra (acc: SingleSignOnAccount) parameter I don't know the syntax to make this working.

I got the params -> ... get { params } from here and it would also be nice if such an example was on the website.

@z3ntu
Copy link

z3ntu commented Dec 21, 2018

I've got it working now by using

single { params -> provideRetrofit(get { params }, params.component1()) }

Such an example should still be put on the website though. Thanks for creating Koin!

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

5 participants