-
I'm a bit confused as to how this injection works. (Bear with me, this is a new concept for me). So say I create my context object in the main part of the application and then register some classes with it. If I want to access said variables from another class do I need to pass this context object via the constructor? Doesn't this defeat the whole purpose? I'm sure there is a better way. If someone could provide an example a bit more conducive to a game scenario I would really appreciate it. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
No, the goal is to keep all the initiation complexity in one place and simplify the process. If you want to create objects with DI at runtime, pass the providers (functional objects) to the appropriate constructors. I know that some of the examples in the Let me give you an example: /** Does a thing. Requires [B] to work. */
class A(val b: B) {
fun work() {
b.work()
}
}
/** A singleton service. */
class B {
fun work() {
println("B!")
}
} We've got an class C(val b: B) {
fun work() {
val a = A(b)
a.work()
}
}
fun main(args: Array<String>) {
val b = B()
val c = C(b)
c.work()
} It might not seem that bad, and it does work as expected - but take a look at the class D(val b: B) {
fun work() {
b.work()
println("D!")
}
} Refactored -/** Does a thing. Requires [B] to work. */
+/** Does a thing. Requires [B] and [D] to work. */
-class A(val b: B) {
+class A(val b: B, val d: D) {
fun work() {
b.work()
+ d.work()
}
} Now -class C(val b: B) {
+class C(val b: B, val d: D) {
fun work() {
- val a = A(b)
+ val a = A(b, d)
a.work()
}
}
fun main(args: Array<String>) {
val b = B()
+ val d = D(b)
- val c = C(b)
+ val c = C(b, d)
c.work()
} So - not only do you need to change the initiation code, but also internal Of course, you might have solved that differently even without DI, but I'd say class C(val aProvider: () -> A) {
fun work() {
val a = aProvider()
a.work()
}
}
fun main(args: Array<String>) {
val context = Context().register {
bindSingleton(B())
bind { A(inject()) }
bindSingleton(C(provider()))
}
val c = context.inject<C>()
c.work()
} The initiation code got a bit longer, but now you don't need local variables - you just use class C(val aProvider: () -> A) {
fun work() {
val a = aProvider()
a.work()
}
}
fun main(args: Array<String>) {
val context = Context().register {
bindSingleton(B())
+ bindSingleton(D(inject()))
- bind { A(inject()) }
+ bind { A(inject(), inject()) }
bindSingleton(C(provider()))
}
val c = context.inject<C>()
c.work()
} You only have to say how to initiate Does this clear things up a bit? |
Beta Was this translation helpful? Give feedback.
-
All of the letters are a bit hard to follow but I think I understand the gist of it. |
Beta Was this translation helpful? Give feedback.
-
TL;DR: with |
Beta Was this translation helpful? Give feedback.
No, the goal is to keep all the initiation complexity in one place and simplify the process. If you want to create objects with DI at runtime, pass the providers (functional objects) to the appropriate constructors.
I know that some of the examples in the
README
pass theContext
around, but this is just an example of its API usage. Normally you'd want to avoid usingContext
directly other than for the initialization phase.Let me give you an example:
We've got an
A
class that requires aB
instance to work. Let's supp…