У меня есть этот (рабочий) код, который расширен из документации 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 Вывод имеет правильное количество элементов, но не ссылается на пользователя. Как я могу это исправить? Я также был бы признателен за информацию о других подходах к отображению вложенных объектов (и списков) в настройку расширения.
Привет Том
Следующая слегка измененная версия, я считаю, делает то, что вы намеревались:
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: '[email protected]')
user(name: 'tim', email: '[email protected]')
}
}
class User {
String name
String email
}
Если вы специально искали, как сделать закрытие конфигурации с двойным вложением для работы с коллекцией, это не решит вашу проблему, но даст вам достаточно чистый способ выполнить то, что предназначено сценарием сборки.
Если вы считаете, что этот ответ отвечает на ваш вопрос, рассмотрите возможность его принятия: stackoverflow.com/help/someone-answers