#[derive(Injectable)]Expand description
Derives the Injectable trait for automatic dependency injection.
This procedural macro generates a constructor and implements the InjectableExtension trait,
enabling automatic dependency resolution through the service container.
§Requirements
- All fields must be wrapped in
Arc<T>whereTis a registered service type - The struct must have named fields or be a unit struct
- All dependency types must be resolvable from the service provider
§Generated Code
The macro generates:
- A
newconstructor that accepts all dependencies as parameters - An
InjectableExtensionimplementation with a factory function that:- Resolves each dependency from the service provider context
- Constructs the type with resolved dependencies
- Returns a boxed instance
§Examples
§Basic Usage with Dependencies
ⓘ
use service_rs::{Injectable, ServiceCollection};
use std::sync::Arc;
// Mock types for demonstration
struct ConnectionPool;
struct Logger;
#[derive(Injectable)]
struct DatabaseService {
connection_pool: Arc<ConnectionPool>,
logger: Arc<Logger>,
}
// Generated code (conceptual):
// impl DatabaseService {
// pub fn new(connection_pool: Arc<ConnectionPool>, logger: Arc<Logger>) -> Self {
// Self { connection_pool, logger }
// }
// }§Unit Struct (No Dependencies)
ⓘ
use service_rs::Injectable;
#[derive(Injectable)]
struct SimpleService;
// Generated code (conceptual):
// impl SimpleService {
// pub fn new() -> Self {
// Self
// }
// }§Registration with Service Collection
ⓘ
use service_rs::{Injectable, ServiceCollection};
use std::sync::Arc;
#[derive(Injectable)]
struct MyService {
dependency: Arc<i32>,
}
let collection = ServiceCollection::new()
.add_singleton_with_factory::<i32, _, _>(|_| async {
Ok(Box::new(42) as Box<dyn std::any::Any + Send + Sync>)
})
.add_singleton::<MyService>(); // Uses Injectable§Compile-Time Errors
The macro will produce compile errors if:
-
Fields are not wrapped in
Arc<T>:ⓘ#[derive(Injectable)] struct BadService { field: String, // Error: must be Arc<String> } -
Used on enums:
ⓘ#[derive(Injectable)] enum BadEnum { Variant } // Error: Injectable only works with structs -
Used with unnamed fields:
ⓘ#[derive(Injectable)] struct BadService(Arc<String>); // Error: must use named fields
§Runtime Behavior
When a service is resolved:
- The factory function is called with a
ServiceProviderContext - Each dependency is resolved asynchronously via
ctx.get::<T>() - If any dependency fails to resolve, an error is propagated
- On success, the constructor is called with all resolved dependencies
§Performance Notes
- Dependencies are resolved lazily when the service is first requested
Arc<T>provides efficient reference counting for shared ownership- Async resolution allows for non-blocking initialization