使用Kotlin我想定义一个DSL来初始化一个结构。如您所见,我想创建一组模块,每个模块都有许多字段。
class DSL : ModuleDSL() {
init {
module(Module("myModule")) {
field("Test", "Test")
field("Test", "Test")
field("Test", "Test")
}
module(Module("myOtherModule")) {
field("Test", "Test")
field("Test", "Test")
field("Test", "Test")
}
}
}
每个字段都必须连接到模块。 Whit在闭包中包含字段定义,afaik我没有对模块的引用。在模块及其字段之间创建连接的最佳方式是什么。
为了完整性,这些是其他类
open class ModuleDSL {
fun field(fieldname: String, attributename: String) {
println("${fieldname} is named ${attributename}")
}
fun module(module: Module, function: () -> Unit) {
function.invoke()
}
fun createModel() {
println("Create my model")
}
}
class Module(name: String) {
init {
println("Create entity ${name}")
}
}
fun main(args: Array<String>) {
val myModuleDsl = DSL()
myModuleDsl.createModel()
}
答案 0 :(得分:0)
经过一些实验,我找到了一个合理的优雅解决方案,从互联网上的一个例子中提取。
配置位于配置类中。与fun main一起看起来像这样:
class MyModuleConfigurator : ModuleConfigurator() {
fun bld() =
module("MyModule1") {
+"Text"
field {
+"Fieldtext 1"
}
field {
+"Fieldtext 2a"
+"Fieldtext 2b"
form("form in field 2")
}
form("Form 1")
}
}
fun main(args: Array<String>) {
val myHTML = MyModuleConfigurator()
myHTML.bld()
}
配置类派生自实现配置标记的主类。有关其他信息,请参阅注释:
open class ModuleConfigurator {
// Triggers on 'module' keyword
protected fun module(name: String, init: Module.() -> Unit) {
val module = Module(name)
module.init()
// Add your post DSL processing operation here
println(module.toString())
}
class Module(val name: String) {
// Triggers on 'field' keyword in the 'module'
fun field(init: Field.() -> Unit) = initTag(this, init)
// Triggers on 'form' keyword
fun form(name: String) {
println("form with name ${name} in module ${this.name}")
}
// Triggers on + keyword
operator fun String.unaryPlus() {
val textElement = ModuleConfigurator.TextElement(this)
println("Module unary plus (name = ${textElement})")
}
// Other module internals
private fun initTag(module: Module, init: Field.() -> Unit) {
val myField = Field(module)
module.add(myField)
myField.init()
}
private fun add(myField: Field) {
// Hook to add field to module
}
override fun toString(): String {
return "Module(${name})"
}
}
// Helper to unwrap the string in the Unary Plus
class TextElement(val text: String) {
override fun toString(): String {
return "$text"
}
}
class Field(val module: ModuleConfigurator.Module) {
operator fun String.unaryPlus() {
val textElement = ModuleConfigurator.TextElement(this)
println("Field unary plus in module ${module.toString()}, text = '${textElement}'")
}
}
}
享受!