2017-08-15 4 views
-2

Kotlinを使用する構造体を初期化するためにDSLを定義したいと思います。あなたが見ることができるように、私は、それぞれがいくつかのフィールドを持つモジュールのセットを作りたいと思っています。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() 

} 
+1

ドキュメントを読んだことがありますか? https://kotlinlang.org/docs/reference/type-safe-builders.html –

+0

これはいいです。その例に基づいて、私が投稿した例を抽出しました。下記参照。 –

答えて

0

の残りの部分です。

設定はコンフィグレーションクラスにあります。

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}'") 
     } 

    } 

} 

お楽しみください!

関連する問題