Следующая слегка измененная версия, которую я считаю, делает то, что вы хотели:
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
}
Если вы специально искали способ создания двухуровневого закрытия конфигурации для работы по сбору, это не решит вашу проблему, но даст вамразумно чистый способ выполнить то, что задумал скрипт сборки.