理解集合
Gradle 提供了用于维护对象集合的类型,这些类型旨在很好地扩展 Gradle 的 DSL 并提供诸如延迟配置之类的有用特性。
可用集合
这些集合类型用于管理对象集合,特别是在构建脚本和插件的上下文中
-
DomainObjectSet<T>
:表示类型 T 的对象集合。此集合不允许重复元素,您可以在其中添加、删除和查询对象。 -
NamedDomainObjectSet<T>
:是DomainObjectSet
的特化,其中每个对象都关联着一个唯一的名称。这常用于需要通过名称唯一标识每个元素的集合。 -
NamedDomainObjectList<T>
:类似于NamedDomainObjectSet
,但表示一个对象列表,其中顺序很重要。每个元素都关联着一个唯一的名称,您可以通过索引和名称访问元素。 -
NamedDomainObjectContainer<T>
:一个用于管理类型 T 对象的容器,其中每个对象都关联着一个唯一的名称。此容器提供了按名称添加、删除和查询对象的方法。 -
ExtensiblePolymorphicDomainObjectContainer<T>
:是NamedDomainObjectContainer
的扩展,允许您为不同类型的对象定义实例化策略。当您有一个可以容纳多种类型对象的容器,并且想要控制每种类型对象的实例化方式时,这会很有用。
这些类型常用于 Gradle 插件和构建脚本中,以管理对象集合,例如任务、配置或自定义领域对象。
1. DomainObjectSet
一个 DomainObjectSet
简单地持有一组可配置的对象。
与 NamedDomainObjectContainer
相比,DomainObjectSet
不管理集合中的对象。它们需要手动创建和添加。
您可以使用 ObjectFactory.domainObjectSet() 方法创建一个实例
abstract class MyPluginExtensionDomainObjectSet {
// Define a domain object set to hold strings
val myStrings: DomainObjectSet<String> = project.objects.domainObjectSet(String::class)
// Add some strings to the domain object set
fun addString(value: String) {
myStrings.add(value)
}
}
abstract class MyPluginExtensionDomainObjectSet {
// Define a domain object set to hold strings
DomainObjectSet<String> myStrings = project.objects.domainObjectSet(String)
// Add some strings to the domain object set
void addString(String value) {
myStrings.add(value)
}
}
2. NamedDomainObjectSet
一个 NamedDomainObjectSet
持有一组可配置的对象,其中每个元素都关联着一个名称。
这类似于 NamedDomainObjectContainer
,但 NamedDomainObjectSet
不管理集合中的对象。它们需要手动创建和添加。
您可以使用 ObjectFactory.namedDomainObjectSet() 方法创建一个实例。
abstract class Person(val name: String)
abstract class MyPluginExtensionNamedDomainObjectSet {
// Define a named domain object set to hold Person objects
private val people: NamedDomainObjectSet<Person> = project.objects.namedDomainObjectSet(Person::class)
// Add a person to the set
fun addPerson(name: String) {
people.plus(name)
}
}
abstract class Person {
String name
}
abstract class MyPluginExtensionNamedDomainObjectSet {
// Define a named domain object set to hold Person objects
NamedDomainObjectSet<Person> people = project.objects.namedDomainObjectSet(Person)
// Add a person to the set
void addPerson(String name) {
people.create(name)
}
}
3. NamedDomainObjectList
一个 NamedDomainObjectList
持有一组可配置的对象列表,其中每个元素都关联着一个名称。
这类似于 NamedDomainObjectContainer
,但 NamedDomainObjectList
不管理集合中的对象。它们需要手动创建和添加。
您可以使用 ObjectFactory.namedDomainObjectList() 方法创建一个实例。
abstract class Person(val name: String)
abstract class MyPluginExtensionNamedDomainObjectList {
// Define a named domain object list to hold Person objects
private val people: NamedDomainObjectList<Person> = project.objects.namedDomainObjectList(Person::class)
// Add a person to the container
fun addPerson(name: String) {
people.plus(name)
}
}
abstract class Person {
String name
}
abstract class MyPluginExtensionNamedDomainObjectList {
// Define a named domain object container to hold Person objects
NamedDomainObjectList<Person> people = project.container(Person)
// Add a person to the container
void addPerson(String name) {
people.create(name: name)
}
}
4. NamedDomainObjectContainer
一个 NamedDomainObjectContainer
管理一组对象,其中每个元素都关联着一个名称。
该容器负责创建和配置元素,并提供构建脚本可用于定义和配置元素的 DSL。它旨在容纳自身可配置的对象,例如一组自定义 Gradle 对象。
Gradle 在整个 API 中广泛使用 NamedDomainObjectContainer
类型。例如,用于管理项目任务的 project.tasks
对象就是一个 NamedDomainObjectContainer<Task>
。
您可以使用 ObjectFactory 服务创建一个容器实例,该服务提供了 ObjectFactory.domainObjectContainer() 方法。这也可以使用 Project.container() 方法获取,但在自定义 Gradle 类型中,通常最好使用注入的 ObjectFactory
服务,而不是传递 Project
实例。
您也可以使用只读的托管属性创建一个容器实例。
abstract class Person(val name: String)
abstract class MyPluginExtensionNamedDomainObjectContainer {
// Define a named domain object container to hold Person objects
private val people: NamedDomainObjectContainer<Person> = project.container(Person::class)
// Add a person to the container
fun addPerson(name: String) {
people.create(name)
}
}
abstract class Person {
String name
}
abstract class MyPluginExtensionNamedDomainObjectContainer {
// Define a named domain object container to hold Person objects
NamedDomainObjectContainer<Person> people = project.container(Person)
// Add a person to the container
void addPerson(String name) {
people.create(name: name)
}
}
为了使用任何 domainObjectContainer()
方法,类型必须满足以下条件之一:
-
是命名托管类型;或
-
暴露一个名为“name”的属性,作为对象的唯一且常量名称。该方法的
domainObjectContainer(Class)
变体通过调用接受字符串参数的类构造函数来创建新实例,该字符串参数即为对象期望的名称。
通过这种方式创建的对象被视为自定义 Gradle 类型,因此可以使用本章讨论的特性,例如服务注入或托管属性。
有关允许自定义实例化策略的 domainObjectContainer()
方法变体,请参阅上面的链接
public interface DownloadExtension {
NamedDomainObjectContainer<Resource> getResources();
}
public interface Resource {
// Type must have a read-only 'name' property
String getName();
Property<URI> getUri();
Property<String> getUserName();
}
对于每个容器属性,Gradle 会自动向 Groovy 和 Kotlin DSL 添加一个块,您可以使用该块来配置容器的内容
plugins {
id("org.gradle.sample.download")
}
download {
// Can use a block to configure the container contents
resources {
register("gradle") {
uri = uri("https://gradle.org.cn")
}
}
}
plugins {
id("org.gradle.sample.download")
}
download {
// Can use a block to configure the container contents
resources {
register('gradle') {
uri = uri('https://gradle.org.cn')
}
}
}
5. ExtensiblePolymorphicDomainObjectContainer
一个 ExtensiblePolymorphicDomainObjectContainer 是一个 NamedDomainObjectContainer
,它允许您为不同类型的对象定义实例化策略。
您可以使用 ObjectFactory.polymorphicDomainObjectContainer() 方法创建一个实例
abstract class Animal(val name: String)
class Dog(name: String, val breed: String) : Animal(name)
abstract class MyPluginExtensionExtensiblePolymorphicDomainObjectContainer(objectFactory: ObjectFactory) {
// Define a container for animals
private val animals: ExtensiblePolymorphicDomainObjectContainer<Animal> = objectFactory.polymorphicDomainObjectContainer(Animal::class)
// Add a dog to the container
fun addDog(name: String, breed: String) {
var dog : Dog = Dog(name, breed)
animals.add(dog)
}
}
abstract class Animal {
String name
}
abstract class Dog extends Animal {
String breed
}
abstract class MyPluginExtensionExtensiblePolymorphicDomainObjectContainer {
// Define a container for animals
ExtensiblePolymorphicDomainObjectContainer<Animal> animals
MyPluginExtensionExtensiblePolymorphicDomainObjectContainer(ObjectFactory objectFactory) {
// Create the container
animals = objectFactory.polymorphicDomainObjectContainer(Animal)
}
// Add a dog to the container
void addDog(String name, String breed) {
animals.create(Dog, name: name, breed: breed)
}
}