Skip to content

Defining and Registering Components

A Component is an injectable struct that is automatically constructed based on dependencies already registered in the container.

This type of struct is ideal for representing modular parts of the application that depend on other services or configurations, such as data repositories, business services, and so on.

Defining a Component

To define a Component, use the #[injectable] attribute on the struct definition.

Tip

The #[injectable(component)] syntax is also valid, but not necessary. Use it only if you want to be explicit about your intention to define a component.

Example

rust
#[injectable]
pub struct TaskRepository {
    db: Arc<Database>,
}

impl TaskRepository {
    pub async fn find_all(&self) -> Vec<Task> {
        sqlx::query_as::<_, Task>("SELECT id, title FROM tasks")
            .fetch_all(self.db.get_pool())
            .await
            .expect("Failed to fetch tasks")
    }

    pub async fn create(&self, task: Task) {
        sqlx::query("INSERT INTO tasks (id, title) VALUES ($1, $2)")
            .bind(task.id)
            .bind(task.title)
            .execute(self.db.get_pool())
            .await
            .expect("Failed to insert task");
    }
}

In this example, TaskRepository does not require a specific constructor. The dependency injection system will resolve each field of the Component and construct it automatically.

You probably noticed that Database is wrapped in an Arc pointer. While not strictly mandatory, this is useful for low-cost cloning, allowing you to share references to the same Component or Provider in multiple places without creating unnecessary clones.

Multiple Injection

A Component can depend on multiple Providers, Components, and structs marked with the #[config] attribute. In the case of config structs, it is not necessary to wrap them in an Arc pointer.

rust
#[config(key = "task")]
#[derive(Clone, Deserialize)]
pub struct TaskConfig {
    max_tasks: usize,
}

#[injectable]
pub struct TaskService {
    repo: Arc<TaskRepository>,
    task_conf: TaskConfig,
}