我是Groovy / Gradle的新手,所以如果我的任何术语出错,请原谅我。
我正在尝试为Gradle编写插件。我想要的是一个自定义任务,可以采用任意名称并使用这些名称创建域对象。这样的事情就是我的目标:
task myTask(type: MyTask) {
hello {
myMethod 'my data'
}
hiagain {
myMethod 'other data'
}
}
hello
和hiagain
分别是每个域对象的名称。我目前只想在顶级做这个,但我可以看到其他用例,我会有几个可能的嵌套级别。还有一种情况是同时具有动态命名的对象,但在这些任务中也有其他特定的属性和方法,但我现在并不关心。
我尝试使用NamedDomainObjectContainer
执行此操作(任务,容器,:
package com.mkobit.gradle
import org.gradle.api.DefaultTask
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Task
class MyTask extends DefaultTask {
NamedDomainObjectContainer<MyContainerData> container
MyTask() {
container = project.container(MyContainerData)
}
@Override
Task configure(Closure closure) {
closure.delegate = container
closure()
this
}
String getGuy(String name) {
container.getByName(name).myValue
}
}
package com.mkobit.gradle
import org.gradle.util.Configurable
class MyContainerData implements Configurable<MyContainerData> {
String myValue
public MyContainerData(String name) {
this.name = name
}
@Override
MyContainerData configure(Closure closure) {
closure.delegate = this
closure()
this
}
void myMethod(String s) {
myValue = s
}
}
package com.mkobit.gradle
import org.gradle.testfixtures.ProjectBuilder
import spock.lang.Specification
class MyTaskTest extends Specification {
def project = ProjectBuilder.builder().build()
def "name test"() {
given:
def task = project.task('myTask', type: MyTask)
expect:
task.name == 'myTask'
}
def "try domain container"() {
given:
def task = project.task('myTask', type: MyTask) {
hello {
myMethod 'my data'
}
hiagain {
myMethod 'other data'
}
}
expect:
task.getGuy('hello') == 'my data'
task.getGuy('hiagain') == 'other data'
}
}
我在文档中看到类似内容的唯一地方位于Chapter 61. Writing Custom Plugins。
的底部这不起作用,当我运行测试时,我得到了这个堆栈跟踪:
没有方法签名:com.mkobit.gradle.MyTaskTest.hello()是 适用于参数类型: (com.mkobit.gradle.MyTaskTest $ __ spock_feature_0_1_closure1 $ _closure2) 值:
...
我不确定如何实现这一目标,或者即使这是正确的方法。
提供的方法更好地包含这些任务吗?然后它看起来像:
task myTask(type: MyTask) {
myHellos {
hello {
myMethod 'my data'
}
hiagain {
myMethod 'other data'
}
}
}
但我仍然不确定我会怎么做。
基本上,如何将任意命名的域对象添加到任务中?
答案 0 :(得分:1)
由于answer提供了不同的@Opal,我能够提出解决方案。 Task
为ExtensionAware
,因此您可以在任务上创建扩展程序。以下是我能够如何调整上述类以获得我在问题底部描述的DSL:
import org.gradle.api.DefaultTask
class MyTask extends DefaultTask {
MyTask() {
def myExtensionContainer = project.container(MyContainerData)
extensions.add('myExtension', myExtensionContainer)
}
}
class MyContainerData {
String myValue
String name
public MyContainerData(String name) {
this.name = name
}
void myMethod(String s) {
myValue = s
}
}
mport org.gradle.testfixtures.ProjectBuilder
import spock.lang.Specification
class MyTaskTest extends Specification {
def project = ProjectBuilder.builder().build()
def "name test"() {
given:
def task = project.task('myTask', type: MyTask)
expect:
task.name == 'myTask'
}
def "try domain container"() {
given:
def task1 = project.task('myTask', type: MyTask) {
myExtension {
hello {
myMethod 'my data'
}
hiagain {
myMethod 'other data'
}
}
}
def task2 = project.task('otherTask', type: MyTask) {
myExtension {
myDude {
myMethod 'other data'
}
}
}
expect:
task1.extensions.myExtension.hello.myValue == 'my data'
task1.extensions.myExtension.hello.name == 'hello'
task1.extensions.myExtension.hiagain.myValue == 'other data'
task1.extensions.myExtension.hiagain.name == 'hiagain'
task2.extensions.myExtension.myDude.myValue == 'other data'
}
}