Search code examples
koin

Can scoping create objects using scope Id as a parameter?


I have a crypto module that provides my keystore, and a factory that allows me to get a secret key from the keystore based on the key name, like so:

var cryptoModule = module {
   single {
      getKeyStore()
   }
   factory { (keyAlias: String) ->
      getKey(keyAlias, get())
   }
}

fun getKeyStore(): KeyStore
fun getKey(keyAlias: String, keyStore: KeyStore) : SecretKey

I then want to be able to create a user session, and get back a SecretKey key based on the userId, which is what I use for the scopeId, like so:

var sessionModule = module {
   scope(name("SESSION")) {
      scoped(name("sessionKey")) { 
         getKey(ScopeID(), get()
      }
   }
}

I'm tryin to get everything going, and I wind up getting crash when I call startKoin and pass it my crypto and session modules - complains about the first parameter to getKey not being provided. I'm attempting to use it like this:

lateinit var userId: String
val sessionScope = getKoin().createScope(userId,name("SESSION"))
val userKey : SecretKey by scope.inject(name("sessionKey"))

So, what am I doing wrong? Can koin support this, or is my thinking about scopes incorrect in some fashion?


Solution

  • I was able to figure this out. The scopeId is available as the parameter "id". I could then create a SecretKey instance using my factory from the crypto module by passing the id to it.

    val sessionModule = module {
        scope (named("session")) {
            // create a SecretKey, with a named attribute
            scoped(named("sessionKey")) {
                // get it from the factory passing in the scope id
                get<SecretKey> { parametersOf(id) }
            }
            scoped {
                // get the session client and use the named session key
                sessionClient(androidContext(), get(), get(), get(named("sessionKey")))
            }
        }
    }
    

    The other key was getting access to the value. Because I need to initialize the session scope with the userId I need to lateinit it, and as such I needed to use the scope.get() method to retrieve an object from the scope.

        private lateinit var sessionScope : Scope
        private val sessionClient : OkHttpClient by lazy {
            sessionScope.get<OkHttpClient>()
        }
    

    Then as long as I don't try and access sessionClient before setting the sessionScope e.g. (sessionScope = getKoin().createScope(userId,named("session")), everything works.