在 Kotlin 的 Injekt 库中,如何注入函数而不仅仅是值?
In the Injekt library for Kotlin, how do I inject functions instead of just values?
在Kotlin中使用Injekt库进行依赖注入时:
有时我想注入一个函数,而不是注入一个值。所以像通过以下方式接收函数:
val function: (Int) -> Int = Injekt.get()
这似乎工作正常,但如果我注册了多个具有相同签名但含义不同的函数,那就不行了。似乎没有办法区分功能。
注: 此题是作者(Self-Answered Questions)特意写下并回答的,所以常用Injekt的地道答案+ Kotlin 主题出现在 SO 中。也欢迎其他答案,还有其他样式的方法!披露,我是 Injekt 库的作者。
你是对的,函数归结为签名的内部表示,例如在这种情况下:
kotlin.jvm.functions.Function1<? super java.lang.Integer, ? extends java.lang.Integer>
并且任何具有相同参数和 return 类型的函数都将具有相同的内部类型并且在 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包装器:
class Int1Action(val function: (Int) -> Int) {
operator fun invoke(i: Int): Int = function(i)
}
加上invoke
运算符,自然可以不用引用function
成员就可以使用这个wrapper,如:
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
在Kotlin中使用Injekt库进行依赖注入时:
有时我想注入一个函数,而不是注入一个值。所以像通过以下方式接收函数:
val function: (Int) -> Int = Injekt.get()
这似乎工作正常,但如果我注册了多个具有相同签名但含义不同的函数,那就不行了。似乎没有办法区分功能。
注: 此题是作者(Self-Answered Questions)特意写下并回答的,所以常用Injekt的地道答案+ Kotlin 主题出现在 SO 中。也欢迎其他答案,还有其他样式的方法!披露,我是 Injekt 库的作者。
你是对的,函数归结为签名的内部表示,例如在这种情况下:
kotlin.jvm.functions.Function1<? super java.lang.Integer, ? extends java.lang.Integer>
并且任何具有相同参数和 return 类型的函数都将具有相同的内部类型并且在 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包装器:
class Int1Action(val function: (Int) -> Int) {
operator fun invoke(i: Int): Int = function(i)
}
加上invoke
运算符,自然可以不用引用function
成员就可以使用这个wrapper,如:
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