将嵌套闭包调用委托给相应的类

时间:2017-01-31 10:43:47

标签: gradle kotlin

我正在尝试在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" }
    }
}

但我对内部闭包有问题,例如srcLinkdownloadPathinstallPath。如何将其invokation委托给相应的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 - 其他字段为空

open class PrintingTask :  DefaultTask() {

    @TaskAction
    fun print() {
        val extension = this.project.extensions.getByName("env")  as ApplicationEnvironmentContainerExtension

        extension.environs.forEach {
            println(it.value)
        }
    }
}

如何将closure委托给ApplicationEnvironmentExtension

3 个答案:

答案 0 :(得分:0)

您永远不会在closure函数中调用app参数。我认为app函数的签名是错误的。它应该是这样的:

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

这使得闭包中的this引用ApplicationEnvironmentExtension。这使得对srcLinkdownloadPathinstallPath的调用击中了正确的对象。

然后通过这样做来调用闭包:

val extension = ApplicationEnvironmentExtension()
extension.closure()

这将填充ApplicationEnvironmentExtension

我还认为srcLinkdownloadPathinstallPath函数的签名是错误的。它们应该像这样定义:

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

答案 1 :(得分:0)

你甚至需要这些功能吗?您是否可以将scrLinkdownloadPathinstallPath设置为属性?即

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

答案 2 :(得分:0)

我使用该解决方法解决了这个问题。

出于一些奇怪的原因,我传递给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)
    }
}

关于关闭,我决定像James Bassett建议的那样设置它们

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