Gradle:如何将列表从配置关闭映射到扩展设置

时间:2019-04-09 07:13:32

标签: groovy gradle-plugin

我有这个(有效的)代码,它是从gradle文档中扩展的

https://docs.gradle.org/4.10.3/userguide/custom_plugins.html#sec:implementing_a_dsl

class User {
    String name
}


class Group {
    User user
}

class GreetingPluginExtension {
    String message
    final Group group

    @javax.inject.Inject
    GreetingPluginExtension(ObjectFactory objectFactory) {
        group = objectFactory.newInstance(Group)
        group.user = objectFactory.newInstance(User)
    }

    void group(Action<? super Group> action) {
        action.execute(group)
    }

    void user(Action<? super User> action) {
        action.execute(group.user)
    }
}

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        // Create the extension, passing in an ObjectFactory for it to use
        def extension = project.extensions.create('greeting', GreetingPluginExtension, project.objects)
        project.task('hello') {
            doLast {
                    println "${extension.message} from ${extension.group.user.name}"
            }
        }
    }
}

配置关闭看起来像这样:

greeting {
    message = 'Hello'
    group {
        user {
            name = 'tom'
        }
    }
}

但是我想要一个我尝试过的用户列表:

class User {
    String name
}


class Group {
    ArrayList<User> users
}

class GreetingPluginExtension {
    String message
    final Group group

    @javax.inject.Inject
    GreetingPluginExtension(ObjectFactory objectFactory) {
        // Create a Person instance
        group = objectFactory.newInstance(Group)
        group.users = []
    }

    void group(Action<? super Group> action) {
        action.execute(group)
    }

    void users(Action<? super ArrayList<User>> action) {
        action.execute(group.users)
    }
}

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        // Create the extension, passing in an ObjectFactory for it to use
        def extension = project.extensions.create('greeting', GreetingPluginExtension, project.objects)
        project.task('hello') {
            doLast {
                extension.group.users.each {

                    println "${extension.message} from ${it.name}"
                }

            }
        }
    }
}

与此关闭:

greeting {
    message = 'Hello'
    group {
        users = [
                {name = 'tom'} ,
                {name = 'tim'}
        ]
    }
}

我的输出如下:

Hello from myProjectName
Hello from myProjectName

这不是预期的输出,而是rootProject.name 输出具有正确数量的元素,但未引用给用户。 我怎样才能解决这个问题?我还希望了解有关将嵌套对象(和列表)映射到扩展设置中的其他方法的信息。

汤姆问候

1 个答案:

答案 0 :(得分:0)

以下我认为稍作修改的版本符合您的意图:

apply plugin: GreetingPlugin

greeting {
    message = 'Hello'
    group {
      user(name: 'tom')
      user(name: 'tim')
    }
}


class User {
    String name
}

class Group {
    ArrayList<User> users = []

    def user(props) {
      users << new User(props)
    }
}

class GreetingPluginExtension {
    String message
    final Group group

    @javax.inject.Inject
    GreetingPluginExtension(ObjectFactory objectFactory) {
        // Create a Person instance
        group = objectFactory.newInstance(Group)
    }

    void group(Action<? super Group> action) {
        action.execute(group)
    }
}

class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        // Create the extension, passing in an ObjectFactory for it to use
        def extension = project.extensions.create('greeting', GreetingPluginExtension, project.objects)
        project.task('hello') {
            doLast {
                extension.group.users.each {
                    println "${extension.message} from ${it.name}"
                }

            }
        }
    }
}

运行时,它会打印:

~> gradle hello

> Task :hello
Hello from tom
Hello from tim

BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

请注意,我已经删除了该方法:

void users(Action<? super ArrayList<User>> action)

,因为上述操作不需要。我还对DSL进行了一些更改。我实际上认为更改过的dsl看起来更易读和惯用,但这当然是个人喜好问题。

还请注意,如果要向用户发送更多属性(例如email),则可以在不修改脚手架代码的情况下执行此操作,即:

greeting {
    message = 'Hello'
    group {
      user(name: 'tom', email: 'tom@wonderland.org')
      user(name: 'tim', email: 'tim@wonderland.org')
    }
}
class User {
    String name
    String email
}

如果您专门在寻找如何为收集工作制作双嵌套配置闭包,这不会解决您的问题,但是确实为您提供了一种相当干净的方法来完成构建脚本的意图。