我正在一个项目中,我想在其中解析一些输入并使用它来调用函数。输入是在运行时处理的字符串,并且要调用的函数由开发人员指定。标记化的输入将传递到指定的函数。
这演示了如何使用代码。您传入一个函数,一些要解析的东西以及一组可以匹配以生成令牌的tokenPatterns。
fun main(args : Array<String>) {
val f = Funcs()
val myColor: String = f.whatColor(Color.GREEN) // Expected
val theirColor: String = Processor.process(f::whatColor, "green", Color.values().toSet())
println(myColor == theirColor) // Should be true
}
class Funcs {
fun whatColor(color: Color): String {
return when (color) {
Color.RED -> "nice red"
Color.GREEN -> "cool green"
}
}
}
enum class Color(override val pattern: Regex) : TokenPattern {
RED(Regex("red")),
GREEN(Regex("green"))
}
下面的代码显示了其当前工作方式的基本版本(或什至无效)。本质上,我基于tokenPatterns集合对输入进行标记化,然后使用这些标记调用指定的函数。问题是我需要将它们强制转换回模式的原始实现(在本例中为Color枚举),以便可以使用它们调用原始函数。
/**
* Extend to define custom tokens.
*/
interface TokenPattern {
val pattern: Regex
}
class Token<T: Any>(val type: KClass<out T>)
/**
* Tokenizes and runs functions
*/
object Processor {
fun process(func: KFunction<String>, input: String, tokenPatterns: Set<TokenPattern>): String {
val tokens = tokenize(input, tokenPatterns)
return runIt(func, tokens)
}
private fun tokenize(input: String, tokenPatterns: Set<TokenPattern>): List<Token<*>> {
return tokenPatterns.filter { it.pattern.matches(input) }.map { Token(it::class) }
}
private fun runIt(func: KFunction<String>, tokens: List<Token<*>>): String {
val args: Array<Any> = tokens.toTypedArray()
// Some casting needs to be done
return func.call(*args)
}
实际的代码要比这复杂得多,但这多少或多或少说明了它们如何协同工作。我遇到的主要问题是我不确定如何动态地转换回Color实现,因此可以使用反射将其传递给函数。我也乐于接受其他方式来完成此任务,任何帮助将不胜感激!谢谢!
答案 0 :(得分:0)
我相信可以通过将基础实现枚举存储或检索到令牌本身中来实现。在此行中,存储了该类,但是我不确定它是指任何颜色还是特定的Color.Red或Color.Green。
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<syncOrderRelationResponse
xmlns="http://www.csapi.org/schema/parlayx/data/sync/v1_0/local">
<result>0</result>
<resultDescription>OK</resultDescription>
</syncOrderRelationResponse>
</soap:Body>
</soap:Envelope
这可能可以恢复,但是我不确定如何写。
tokenPatterns.filter { it.pattern.matches(input) }.map { Token(it::class) }
也许我可以不用强制转换来重新创建枚举了?
答案 1 :(得分:0)
只需将tokenPattern存储到令牌中,然后将这些tokenPattern作为args传递,然后反射就可以正确地对其进行强制转换。
您可以像这样制作令牌:
private fun runIt(func: KFunction<String>, tokens: List<Token>): String {
val args: Array<Any> = tokens.map { it.original }.toTypedArray()
return func.call(*args)
}
然后像这样调用函数:
${Properties#fqdn}