Gradle: как сопоставить списки от закрытия конфигурации до настроек расширения - PullRequest
0 голосов
/ 09 апреля 2019

У меня есть этот (рабочий) код, который расширен из документации 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 голосов
/ 09 апреля 2019

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

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
}

Если вы специально искали способ создания двухуровневого закрытия конфигурации для работы по сбору, это не решит вашу проблему, но даст вамразумно чистый способ выполнить то, что задумал скрипт сборки.

...