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

时间:2015-02-16 19:26:52

标签: gradle

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

family {
  mother {
      firstname = 'John'
      lastname  = 'Cleese'
  }
  children {
      son {
        firstName = 'John'
        lastName  = 'Cleese'
      }
      daughter {
        firstName = 'Jane'
        lastName  = 'Cleese'
      }
  }
}

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

显示问题的代码 - 我想将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)
  }
}
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'
      }
  }
}

2 个答案:

答案 0 :(得分:1)

我遇到了类似的问题,但我想出了如何在我的案子中创造“母亲”,而不是“孩子”。我完成此操作的方式是使用嵌套扩展对象。

这是我如何做到这一点(我的是纯java,所以你可能需要做一些改变才能在Groovy中做到这一点 - 我对Groovy很新,所以我不确定究竟需要改变什么):

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

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

这样只允许单个母亲完全宣布。但是请注意,它不会强制执行任何一个,因为您可以添加任意数量的母亲,但任何后来的声明都会导致更改该单个实例的值,因此实际上只有一个。如果母亲没有被宣布,你也可能得到一个空值,所以必须测试它(一些演示说这可能发生,但在我自己的实验中似乎没有)。

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

FamilyExtension fext = project.getExtensions().findByType(Person.class)
Person mother = (Person) ((ExtensionAware) fext).getExtensions().findByName("mother")

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

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;
}

答案 1 :(得分:0)

好吧,要向mother添加family封闭,请将以下代码添加到FamilyExtension

Person mother(Closure closure) {
   mother = new Person()
   project.configure(mother, closure)
   return mother
}

如果您想在家庭内部进行children扩展,请将以下代码添加到FamilyPlugin.apply方法

project.extensions.create("family", FamilyExtension, instantiator, project)
project.family.extensions.create("children", FamilyExtension.Children, project)

然后你添加

void son(Closure closure) {
    Person son = new Person()
    project.configure(son, closure)
    children.add(son)
}

能够在son内添加children封闭。

要查看整个项目和详细说明,请访问Github项目https://github.com/andriipanasiuk/family-gradle-plugin