在Kotlin的Injekt库中,我如何注入函数而不是值?
在Kotlin中使用Injekt库进行dependency injection时:
有时我想注入一个函数,而不是注入一个值。 所以像通过以下方式接收function:
val function: (Int) -> Int = Injekt.get()
这似乎工作正常,但不是如果我注册多个函数具有相同的签名,但意义不同。 似乎没有办法区分这些function。
注意: 这个问题是由作者故意编写和回答的( 自我回答问题 ),所以对于常见的Injekt + Kotlin主题的习惯性的回答在SO中出现。 其他答案也欢迎,还有其他样式的如何做到这一点! 披露,我是Injekt图书馆的作者。
你是对的,函数归结为签名的内部表示,例如在这种情况下:
kotlin.jvm.functions.Function1 super java.lang.Integer, ? extends java.lang.Integer>
而任何具有相同参数和返回types的函数将具有相同的内部types,并且看起来与Injekt相同。 以下注册全部有效且不冲突:
// 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)
如果你想使用相同的函数签名作为不同的含义,你可以为函数的每个含义创建一个类包装:
class Int1Action(val function: (Int) -> Int) { operator fun invoke(i: Int): Int = function(i) }
通过添加invoke
操作符,你可以自然地使用这个包装器而不引用function
成员,比如:
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