我有这个(有效的)代码,它是从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 输出具有正确数量的元素,但未引用给用户。 我怎样才能解决这个问题?我还希望了解有关将嵌套对象(和列表)映射到扩展设置中的其他方法的信息。
汤姆问候
答案 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
}
如果您专门在寻找如何为收集工作制作双嵌套配置闭包,这不会解决您的问题,但是确实为您提供了一种相当干净的方法来完成构建脚本的意图。