Skip to content

Commit c4468b7

Browse files
committed
Support for DI default values
1 parent 7e637dc commit c4468b7

File tree

3 files changed

+32
-8
lines changed
  • reactivestate-core/src
    • commonMain/kotlin/com/ensody/reactivestate
    • commonTest/kotlin/com/ensody/reactivestate

3 files changed

+32
-8
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ReactiveState
22

3-
[![Maven Central](https://img.shields.io/maven-central/v/com.ensody.reactivestate/reactivestate-core)](https://central.sonatype.com/artifact/com.ensody.reactivestate/reactivestate-core-android)
3+
[![Maven Central](https://img.shields.io/maven-central/v/com.ensody.reactivestate/reactivestate-core?color=%2345cf00)](https://central.sonatype.com/artifact/com.ensody.reactivestate/reactivestate-core)
44

55
Kotlin Multiplatform ViewModels and reactive state management based on `StateFlow`.
66

reactivestate-core/src/commonMain/kotlin/com/ensody/reactivestate/DI.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,17 @@ public class DIImpl {
118118
}
119119

120120
// We hide this function as an extension, so nobody can mistakenly get() arbitrary T values not belonging to the DI
121-
public inline fun <reified T : Any> DIResolver.get(): LazyProperty<T> =
122-
InternalDI.run { get(this@get, T::class) }
123-
124-
public fun <T : Any> InternalDI.get(resolver: DIResolver, klass: KClass<T>): LazyProperty<T> {
121+
public inline fun <reified T : Any> DIResolver.get(noinline default: (() -> T)? = null): LazyProperty<T> =
122+
InternalDI.run { get(this@get, T::class, default) }
123+
124+
public fun <T : Any> InternalDI.get(
125+
resolver: DIResolver,
126+
klass: KClass<T>,
127+
default: (() -> T)? = null,
128+
): LazyProperty<T> {
129+
if (default != null && klass !in deps) {
130+
register(klass) { default() }
131+
}
125132
val state = deps.getValue(klass)
126133
resolver.run { owner }?.also {
127134
// A DI module/node must not resolve any deps eagerly, so we can support circular dependencies.

reactivestate-core/src/commonTest/kotlin/com/ensody/reactivestate/DITest.kt

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,21 @@ internal class DITest {
1313
val testDI = DIImpl()
1414

1515
init {
16-
testDI.register { FooDeps(get(someConfigFlag), barDeps) }
16+
testDI.register { FooDeps(get(someConfigFlag), barDeps, defaultDeps) }
1717
testDI.register { BarDeps(fooDeps) }
1818
}
1919

20+
private val defaultFlow = testDI.derived { get(defaultDeps) }
21+
private val default = defaultFlow.value
2022
private val fooFlow = testDI.derived { get(fooDeps) }
2123
private val foo = fooFlow.value
2224
private val barFlow = testDI.derived { get(barDeps) }
2325
private val bar = barFlow.value
2426

2527
@Test
2628
fun stability() {
29+
assertSame(default, testDI.derived { get(defaultDeps) }.value)
30+
assertSame(default, foo.defaultDeps)
2731
assertSame(foo, testDI.derived { get(fooDeps) }.value)
2832
assertSame(bar, testDI.derived { get(barDeps) }.value)
2933
}
@@ -37,16 +41,17 @@ internal class DITest {
3741
testDI.register {
3842
// This causes a too early access
3943
get(barDeps)
40-
FooDeps(get(someConfigFlag), barDeps)
44+
FooDeps(get(someConfigFlag), barDeps, defaultDeps)
4145
}
4246
assertFailsWith<IllegalStateException> { barFlow.value.configFlag }
4347
}
4448

4549
@Test
4650
fun updateDIGraphOnRegister() {
4751
// Replacing FooDeps invalidates the whole subgraph depending on FooDeps. So, BarDeps gets re-created.
48-
testDI.register { FooDeps(get(someConfigFlag), barDeps) }
52+
testDI.register { FooDeps(get(someConfigFlag), barDeps, defaultDeps) }
4953
assertNotSame(foo, testDI.derived { get(fooDeps) }.value)
54+
assertSame(default, testDI.derived { get(fooDeps) }.value.defaultDeps)
5055
val newBar = testDI.derived { get(barDeps) }.value
5156
assertNotSame(bar, newBar)
5257
assertTrue(foo.circularConfigFlag)
@@ -72,6 +77,16 @@ internal class DITest {
7277
}
7378
}
7479

80+
// -------------
81+
// module DefaultDeps
82+
// -------------
83+
84+
// Convenience accessor for FooDeps
85+
private val DIResolver.defaultDeps: LazyProperty<DefaultDeps>
86+
get() = DI.run { get { DefaultDeps() } }
87+
88+
private class DefaultDeps(val value: Boolean = true)
89+
7590
// -------------
7691
// module foo
7792
// -------------
@@ -83,9 +98,11 @@ private val DIResolver.fooDeps: LazyProperty<FooDeps> get() = DI.run { get() }
8398
private class FooDeps(
8499
val configFlag: Boolean,
85100
lazyBarDeps: LazyProperty<BarDeps>,
101+
lazyDefaultDeps: LazyProperty<DefaultDeps>,
86102
) {
87103
// All deps have to be resolved lazily
88104
val barDeps by lazyBarDeps
105+
val defaultDeps by lazyDefaultDeps
89106

90107
// All deps have to be resolved lazily
91108
val circularConfigFlag by lazy { barDeps.configFlag }

0 commit comments

Comments
 (0)