了解集合
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,构建脚本可以使用该 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)
}
}