делегировать вложенную закрытую закрытие соответствующего класса

Я пытаюсь внедрить плагин gradle в kotlin , который поддерживал бы структуру, подобную этой

 env { app ("ghc-haskell") { srcLink { "http://downloads.haskell.org/~ghc/8.0.1/ghc-8.0.1-x86_64-unknown-mingw32.tar.xz" } downloadPath { project(':').projectDir.absolutePath + "\\applications\\plugin" } installPath { project(':').projectDir.absolutePath + "\\applications\\plugin" } } } 

Но у меня проблема с внутренними закрытиями, такими как srcLink , downloadPath , installPath . Как передать свою инволюцию соответствующему классу kotlin ?

Мое расширение выглядит так

 /** * Keeps all environments. */ open class ApplicationEnvironmentContainerExtension { val environs = mutableMapOf<String, ApplicationEnvironmentExtension>() fun app(id: String, closure : ApplicationEnvironmentContainerExtension.() -> String) : ApplicationEnvironmentExtension { val extension = ApplicationEnvironmentExtension() extension.installationId = id environs.put(id, extension) return extension } /** * Sub extension. */ open class ApplicationEnvironmentExtension { var installationId = "" var srcLink = "" var downloadPath = "" var installPath = "" fun srcLink(closure: ApplicationEnvironmentExtension.() -> String) { srcLink = closure() } fun downloadPath(closure: ApplicationEnvironmentExtension.() -> String) { downloadPath = closure() } fun installPath(closure: ApplicationEnvironmentExtension.() -> String) { installPath = closure() } override fun toString(): String { return "ApplicationEnvironmentExtension(" + "installationId='$installationId', " + "srcLink='$srcLink', " + "downloadPath='$downloadPath', " + "installPath='$installPath')" } } } 

И когда я вызываю задачу print для отображения списка окружений, она показывает set only installationId – другие поля пусты

 open class PrintingTask : DefaultTask() { @TaskAction fun print() { val extension = this.project.extensions.getByName("env") as ApplicationEnvironmentContainerExtension extension.environs.forEach { println(it.value) } } } 

Как вызов closure делегата в ApplicationEnvironmentExtension ?

Вы никогда не вызываете параметр closure в своей функции app . Я думаю, что подпись функции app неверна. Это должно быть так:

 fun app(id: String, closure: ApplicationEnvironmentExtension.() -> Unit) 

Это делает this в закрытии ссылкой на ApplicationEnvironmentExtension . Это делает вызовы srcLink , downloadPath и installPath попадают в правый объект.

Затем вы вызываете закрытие, делая следующее:

 val extension = ApplicationEnvironmentExtension() extension.closure() 

Это заполнит ApplicationEnvironmentExtension .

Я также думаю, что подписи функций srcLink , downloadPath и installPath неверны. Они должны быть определены следующим образом:

  fun srcLink(closure: () -> String) fun downloadPath(closure: () -> String) fun installPath(closure: () -> String) 

Вам даже нужны эти функции? Не можете ли вы установить scrLink , downloadPath и installPath как свойства? т.е.

 env { app ("ghc-haskell") { srcLink = "http://downloads.haskell.org/~ghc/8.0.1/ghc-8.0.1-x86_64-unknown-mingw32.tar.xz" downloadPath = project(':').projectDir.absolutePath + "\\applications\\plugin" installPath = project(':').projectDir.absolutePath + "\\applications\\plugin" } } 

Я решил проблему, используя этот способ обхода.

По некоторым странным причинам closure параметра, которое я передавал в метод app всегда хотело разрешить против ApplicationEnvironmentContainerExtension несмотря на то, что установка является закрытием ApplicationEnvironmentExtension и даже вызовом.

Поэтому я решил использовать грубую силу и создать поля, которые должны быть заполнены в ApplicationEnvironmentExtension в ApplicationEnvironmentContainerExtension , заполнить их и установить вручную в требуемом классе.

 open class ApplicationEnvironmentContainerExtension { val environs = mutableMapOf<String, ApplicationEnvironmentExtension>() var installationId = "" var srcLink = "" var installPath = "" var downloadPath = "" fun app(id: String, closure : ApplicationEnvironmentExtension.() -> Unit) { val extension = ApplicationEnvironmentExtension() extension.installationId = id environs.put(id, extension) extension.process(closure) extension.setEverything(installationId, srcLink, downloadPath, installPath) } } 

Что касается закрытия, я решил установить их, как предложил Джеймс Бассетт

 env { app ("ghc-haskell") { srcLink = "http://downloads.haskell.org/~ghc/8.0.1/ghc-8.0.1-x86_64-unknown-mingw32.tar.xz" downloadPath = "$path\\applications\\plugin" installPath = "$path\\applications\\plugin" } app ("mongo-db") { srcLink = "https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-3.4.1-signed.msi" downloadPath = "$path\\applications\\plugin" installPath = "$path\\applications\\plugin" } }