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と同じですね。。