Kotlin用DIフレームワークをつくってみた
つくってみました。
その名もInjeKTor。
この名前かなり気に入ってます。
全コードはこちら→https://github.com/ntaro/InjeKTor
以前書いたエントリでKotlinの委譲のための機能を紹介しました。
これを活かすためにコンストラクタ・インジェクションを行います。
例えばこんな感じのインタフェースと実装クラスがあったとします。
trait Foo class FooImpl: Foo trait Bar class BarImpl(foo: Foo): Bar, Foo by foo class Baz(bar: Bar): Bar by bar
Bazを使いたかったら通常はこうします。
val baz = Baz(BarImpl(FooImpl()))
InjeKTorを使うと次のように書けます。
val injector = createInjector {
javaClass<Foo>() to javaClass<FooImpl>()
javaClass<Bar>() to javaClass<BarImpl>()
}
val baz = injector.getInstance(javaClass<Baz>())
createInjector関数でInjectorインスタンスを生成しています。引数に関数オブジェクトを取って、そこでインタフェースと実装クラスの対応関係を設定しています。Injector#getInstanceで依存性を注入されたBazクラスのインスタンスを生成して返しています。
プロパティへのインジェクションもできます。
class Hoge
class Fuga {
private val hoge by LazyInjector(javaClass<Hoge>())
}
KotlinのDelegated Propertyという機能を使って実現しています。
KotlinでGuiceを使う
KotlinからGuice、使えます→Kotlin + Guiceやってみた
Guice使って最初の例と同じのを書くとこうなります。
trait Foo
class FooImpl : Foo
trait Bar
class BarImpl [Inject](foo: Foo) : Bar, Foo by foo
class Baz [Inject](bar: Bar) : Bar by bar
fun main(args: Array<String>) {
val injector = Guice.createInjector(object: AbstractModule() {
override fun configure() {
bind(javaClass<Foo>()).to(javaClass<FooImpl>())
bind(javaClass<Bar>()).to(javaClass<BarImpl>())
}
})
val baz = injector.getInstance(javaClass<Baz>())
}
だいたいInjeKTorと同じですね。。