将对象实例添加到gradle插件扩展

LK_*_*K__ 7 gradle

我有类似下面的插件,我有一个外部命名空间,在其中有mother一个对象的"具体"实例()加上另一个集合(children).

family {
  mother {
      firstname = 'John'
      lastname  = 'Cleese'
  }
  children {
      son {
        firstName = 'John'
        lastName  = 'Cleese'
      }
      daughter {
        firstName = 'Jane'
        lastName  = 'Cleese'
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

我能够添加集合对象并根据我见过的各种示例读取变量但不确定如何添加具体实例.
如何在扩展对象上定义它?

显示问题的代码 - 我想将mother插件添加为单个实例.

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.*

class Person
{
  final String name
  String firstName
  String lastName
  Person(String name) { this.name = name }
}

class FamilyExtension {

  final NamedDomainObjectContainer<Person> children
  Person mother
  Person father

  FamilyExtension(children) {
    this.children = children
  }

  def children(Closure closure) {
    children.configure(closure)
  }
}

class FamilyPlugin implements Plugin<Project> {

  void apply(Project project) {
    project.task('sayHello', type: DefaultTask) << { 
      println(
        "Hello ${project.family.children["son"].firstName} " +
        "and hello ${project.family.children["daughter"].firstName} ")
    }

    def children  = project.container(Person)

    project.extensions.create("family", FamilyExtension, children)
  }
}
Run Code Online (Sandbox Code Playgroud)
apply plugin: FamilyPlugin

family {
  // How do I add support for this?
  // mother {
  //     firstname = 'John'
  //     lastname  = 'Cleese'
  // }
  children {
      son {
        firstName = 'John'
        lastName  = 'Cleese'
      }
      daughter {
        firstName = 'Jane'
        lastName  = 'Cleese'
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*hew 4

我遇到了与你类似的问题,但我想出了如何在我的案例中创建“母亲”,而不是“孩子”。我完成此任务的方法是使用嵌套扩展对象。

以下是我的做法(我的是纯 java 语言,所以您可能需要进行一些更改才能在 Groovy 中执行此操作 - 我对 Groovy 很陌生,所以我不确定到底需要更改什么):

当您在插件中添加扩展时,该类将自动支持 ExtensionAware 接口,因此可以向其中添加扩展。在 FamilyExtension 构造函数中添加一个新扩展,首先将该类强制转换为 ExtensionAware:

public FamilyExtension(NamedDomainObjectContainer<Person> children) {
    ((ExtensionAware) this).getExtensions().create("mother",Person.class);
    this.children = children;
}
Run Code Online (Sandbox Code Playgroud)

这只会允许与您完全一样的单身母亲申报。但请注意,它不会只强制执行一个,因为您可以根据需要添加任意多个母亲,但任何后续声明都将导致更改该单个实例上的值,因此实际上只有一个。如果未声明母亲,您也可能会得到一个空值,因此必须对此进行测试(一些演示说这种情况可能会发生,但在我自己的实验中似乎不会发生)。

要获取您的母亲对象,只需将您的扩展转换为 ExtensionAware 并从中检索 Person 类,就像您从项目中获取系列扩展一样

FamilyExtension fext = project.getExtensions().findByType(Person.class)
Person mother = (Person) ((ExtensionAware) fext).getExtensions().findByName("mother")
Run Code Online (Sandbox Code Playgroud)

编辑:另一种方法是在扩展对象上定义一个函数,该函数接受闭包并将闭包委托给新的母对象。然后,您可以使用布尔标志来强制执行只有一位母亲的要求。

private boolean mother_defined = false;
private Person mother_value = null;  // or Person mother = new Person()

public void mother(Closure<?> motherdef) {
    if (mother_defined) {throw new Exception("Only one mother allowed");}
    mother_value = new Person();
    motherdef.setDelegate(mother);
    motherdef.call();
    mother_defined = true;
}
Run Code Online (Sandbox Code Playgroud)