将嵌套闭包调用委托给相应的类
我正在试图在kotlin
中实现gradle
插件来支持这样的结构
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
任务来显示环境列表时,它只显示设置的installationId
ID – 其他字段是空的
open class PrintingTask : DefaultTask() { @TaskAction fun print() { val extension = this.project.extensions.getByName("env") as ApplicationEnvironmentContainerExtension extension.environs.forEach { println(it.value) } } }
如何将closure
调用委托给ApplicationEnvironmentExtension
?
你永远不要在你的app
函数中调用closure
参数。 我认为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" } }
我使用该解决方法解决了该问题。
出于一些奇怪的原因,我传入的app
方法中的参数closure
总是要解决ApplicationEnvironmentContainerExtension
尽管设置是作为ApplicationEnvironmentExtension
的关闭,甚至调用它。
所以我决定使用蛮力并在ApplicationEnvironmentExtension
创建应该在ApplicationEnvironmentExtension
中填充的字段,填充它们并在需要的类中手动设置。
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" } }