2016-05-31 6 views
2

Wenn für Dependency Injection Injekt Bibliothek in Kotlin mit:In der Injekt-Bibliothek für Kotlin, wie injiziere ich Funktionen statt nur Werte?

Statt einen Wert von Injektion, manchmal eine Funktion injizieren ich will. So etwas wie die Funktion Empfang von:

val function: (Int) -> Int = Injekt.get() 

Dies scheint ok zu arbeiten, aber nicht, wenn ich mich registriere mehr als eine Funktion mit der gleichen Signatur aber anderer Bedeutung. Es scheint keine Möglichkeit zu geben, die Funktionen zu unterscheiden.

Hinweis:diese Frage absichtlich geschrieben und beantwortete vom Autor (Self-Answered Questions), so dass die idiomatischen Antworten auf häufig gestellte Injekt + Kotlin Themen in SO vorhanden sind. Andere Antworten sind auch willkommen, es gibt andere Stile, wie man das macht! Offenlegung, ich bin der Autor der Injekt-Bibliothek.

Antwort

3

Sie sind richtig, kochen die Funktionen auf eine interne Darstellung der Signatur nach unten, zum Beispiel in diesem Fall:

kotlin.jvm.functions.Function1<? super java.lang.Integer, ? extends java.lang.Integer> 

Und jede Funktion, die den gleichen Parameter hat und Typen zurückgeben müssen der gleiche interne Typ und scheinen für Injekt identisch zu sein. Folgende Anmeldungen sind alle gültig und nicht miteinander kollidieren:

// register some functions 

Injekt.addSingletonFactory { 
    val function: (value: Int) -> Int = { value -> value + 1 } 
    function 
} 

Injekt.addSingletonFactory { 
    val function: (Long) -> Long = { value -> value - 1 } 
    function 
} 

Injekt.addSingletonFactory { 
    val function: (Long) -> String = { value -> "The long is $value" } 
    function 
} 

// inject and use the functions 

val intFunction: (Int) -> Int = Injekt.get() 
val intResult = intFunction(2) 

val longFunction: (Long) -> Long = Injekt.get() 
val longResult = longFunction(2) 

val longStringFunction: (Long) -> String = Injekt.get() 
val stringResult = longStringFunction(10) 

Wenn Sie die gleiche Funktion Signatur als andere Bedeutung verwenden möchten, können Sie eine Wrapper-Klasse für jede Bedeutung der Funktion erstellen:

class Int1Action(val function: (Int) -> Int) { 
    operator fun invoke(i: Int): Int = function(i) 
} 

den invoke Operator Durch das Hinzufügen können Sie selbstverständlich diesen Wrapper verwenden, ohne Bezugnahme auf das function Mitglied, wie zum Beispiel:

Injekt.addSingletonFactory { 
    val function: (Int) -> Int = { value -> value + 20 } 
    Int1Action(function) 
} 

val action: Int1Action = Injekt.get() 
val result = action(2) // call it directly using the invoke operator