Gradle: как сопоставить списки от закрытия конфигурации до настроек расширения

У меня есть этот (рабочий) код, который расширен из документации 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 Вывод имеет правильное количество элементов, но не ссылается на пользователя. Как я могу это исправить? Я также был бы признателен за информацию о других подходах к отображению вложенных объектов (и списков) в настройку расширения.

Привет Том

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
832
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Следующая слегка измененная версия, я считаю, делает то, что вы намеревались:

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

Matias Bjarland 09.04.2019 16:54

Другие вопросы по теме