Gradle offers the NamedDomainObjectContainer class to create a collection of objects defined using a clean DSL. The only requirement for the objects we want to create is that they have a constructor that takes a String argument and a name property to identify the object. The value for the name property must be unique within the collection of objects. We create a new instance of a NamedDomainObjectContainer with the container method of the Gradle Project class. We can add the NamedDomainObjectContainer instance to the extensions property of our project, so we can use a DSL to create instances of objects that need to be in the NamedDomainObjectContainer object in our project.

The following code shows a simple build script in which we want to create a collection of Product objects. The creation of the NamedDomainObjectContainer object is done in a plugin so we only have to apply the plugin to use the DSL to create Product objects:

apply plugin: ProductsPlugin

// DSL to define new objects of type Product.
products {
    // Create Product with name pencil.
    pencil {
        price = 0.05
    }
    // Create Product with name crayon.
    crayon {
        price = 0.18
    }
}


class ProductsPlugin implements Plugin {
    void apply(final Project project) {
        // Create NamedDomainObjectContainer instance for
        // a collection of Product objects
        NamedDomainObjectContainer productContainer =
            project.container(Product)

        // Add the container instance to our project
        // with the name products.
        project.extensions.add('products', productContainer)

        // Simple task to show the Product objects
        // that are created by Gradle using
        // the DSL syntax in our build file.
        project.task('reportProducts') << {
            def products = project.extensions.getByName('products')

            products.all {
                // A Product instance is the delegate
                // for this closure.
                println "$name costs $price"
            }
        }
    }
}

class Product {
    // We need a name property
    // so the object can be created
    // by Gradle using a DSL.
    String name

    BigDecimal price

    Product(final String name) {
        this.name = name
    }
} 

We can run the reportProducts task to see the name and price properties of the Product instances:

$ gradle -q reportProducts
crayon costs 0.18
pencil costs 0.05
$

Written with Gradle 2.11.

Original blog post

shadow-left