LoginSignup
31
34

More than 5 years have passed since last update.

Kotlinで20行でDIコンテナを書いた

Posted at

社内の勉強会で、matzがruby20行でDIコンテナを書いた話が話題になり、kotlinで実装してみました。
現状の実装だとすべてSingletonとなってしまいますが、シンプルさを優先ということで。

ソースをyamamotoj/DISampleにおいておきます。

DIコンテナ本体

DIContainer.kt

class DIContainer {
    private class Item<T : Any>(val resolver: (DIContainer) -> T) {
        private var instance: T? = null
        fun resove(container: DIContainer) =
                instance ?: resolver(container).apply { instance = this }
    }

    private val items = mutableMapOf<String, Item<out Any>>()
    private fun <T> createKey(cls: Class<T>, name: String?): String = cls.name + name

    @Suppress("UNCHECKED_CAST")
    fun <T : Any> resolve(cls: Class<T>, name: String? = null): T =
            synchronized(items) { (items[createKey(cls, name)] as Item<T>) }.resove(this)

    fun <T : Any> register(cls: Class<T>, name: String? = null, resolver: (DIContainer) -> T) =
            synchronized(items) { items.put(createKey(cls, name), Item(resolver)); Unit }
}

依存関係の定義

今回injectするクラス群はこちら

class A()
class B(val a: A)
class C()
class D(val b: B, val c: C)

Application classで依存関係を定義します。

DISampleApplication.kt
class DISampleApplication : Application() {
    val container by lazy {

        // dependency definition
        DIContainer().apply {
            register(A::class.java) { A() }
            register(B::class.java) { B(resolve(A::class.java)) }
            register(C::class.java) { C() }
            register(D::class.java) { D(resolve(B::class.java), resolve(C::class.java)) }
        }
    }
}

Activityへの注入

by lazyが便利です。

MainActivity.kt

class MainActivity : AppCompatActivity() {

    // inject
    val d by lazy { (application as DISampleApplication).container.resolve(D::class.java) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Log.d("log", d.toString())
    }
}

31
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
34