Gradle api 文档指出Project
,可以通过以下方式向项目添加动态方法
项目的一个属性,其值为闭包。闭包被视为一种方法,并使用提供的参数进行调用。该物业的位置如上所述。
我想“如上所述”意味着可以使用动态项目属性。这些在 api 文档中描述为
一个项目有 5 个属性“范围”,用于搜索属性。您可以通过构建文件中的名称或通过调用项目的 property(String) 方法来访问这些属性。范围是:
...
- 项目的额外属性。每个项目都维护一个额外属性的映射,其中可以包含任意名称 -> 值对。一旦定义,该范围的属性就是可读可写的。有关更多详细信息,请参阅额外属性。
所以我想我可以写一个约定插件,例如“sayHello.gradle.kts”
// sayhello.gradle.kts
val sayHello : (String) -> Unit = { who ->
println("Hello $who")
}
ext.set("sayHello", sayHello)
然后使用我在另一个项目中添加的函数(或 lambda)build.gradle.kts
// Some projects build.gradle.kts
plugins {
id("sayHello")
}
sayHello("René")
但我越来越
Script compilation errors:
Line 7: sayHello("")
^ Expression 'sayHello' cannot be invoked as a function. The function 'invoke()' is not found
Line 7: sayHello("")
^ Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public val TaskContainer.sayHello: TaskProvider<DefaultTask> defined in org.gradle.kotlin.dsl
我认为我对 Kotlin DSL 的理解是错误的,并阅读了Extra Properties部分,但这仅显示了值的注册方式,而不是闭包。
尽管如此,我还是尝试注册一个类似于示例值的闭包。所以我做了:
val sayHelloFun : (String) -> Unit = { who ->
println("Hello $who")
}
val sayHello by extra(sayHelloFun)
我收到了同样的错误消息。
有谁知道如何使用 Kotlin DSL 将自定义函数添加到Project
约定插件中?
Kotlin DSL 中不提供动态属性访问
不幸的是,无法
Project
通过 Kotlin DSL 中的预编译脚本插件以这种方式向对象添加函数。文档中讨论“五个项目范围”的部分预计用户正在编写 Groovy 构建脚本,对于 Kotlin 来说并不严格准确:此类访问依赖于 Groovy 语言的动态功能。为了证明这一点,请查看有关使用额外属性的文档。如果比较 Kotlin 和 Groovy 示例,您会发现所有 Kotlin 额外属性都必须使用属性的字符串名称作为键来访问,例如通过编写
extra["myProperty"]
,而 Groovy 可以直接访问它们。备择方案
由于 Kotlin 是静态类型的,因此我们需要一个 Kotlin 编译器可以看到的真实方法。我建议使用两种替代方案来实现此目的:Gradle 扩展和 Kotlin 扩展函数。
Gradle 扩展
当您创建扩展时,Gradle 会为该扩展创建一个访问器。您可以使用它在应用插件的项目中创建一个函数,只不过您需要在扩展上调用它而不是
Project
直接调用它:Kotlin 扩展函数
这种方法只是利用了Kotlin 语言的常规功能。此类函数必须在 buildscript 类路径上的代码中定义,因此这在预编译脚本插件中不起作用(根据您的问题)。
buildSrc
但是,此类代码可以编写在文件夹1中的常规 Kotlin 文件中。然后你可以简单地这样做:1此类代码也可以编写在类定义插件的编译内。