#![allow(warnings)]
use injectable_rs::*;
use std::sync::atomic::{AtomicU32, Ordering};
#[injectable]
#[derive(Default, Debug)]
pub struct AppConfig;
#[injectable]
#[derive(Default, Debug)]
pub struct Database;
#[derive(Default, Debug)]
pub struct RequestHandler {
pub id: u32,
}
#[injectable(scope = Transient)]
impl RequestHandler {
#[injectable(ctor)]
fn new() -> Self {
Self::default()
}
}
#[derive(Debug)]
pub struct TransientProcessor {
pub id: u32,
}
#[injectable(scope = Transient)]
impl TransientProcessor {
#[injectable(ctor)]
fn new() -> Self {
static COUNTER: AtomicU32 = AtomicU32::new(0);
let id = COUNTER.fetch_add(1, Ordering::SeqCst);
println!(" Creating TransientProcessor #{id}");
Self { id }
}
}
#[tokio::main]
async fn main() {
println!("=== Scopes Example ===\n");
let container = Container::builder()
.build()
.await
.expect("container should build");
println!("1. Singleton scope (default):");
let _config1 = container
.resolve::<AppConfig>()
.await
.expect("resolve AppConfig");
let _config2 = container
.resolve::<AppConfig>()
.await
.expect("resolve AppConfig");
println!(" Resolved AppConfig twice");
println!(" (Each resolution creates a new instance; true singleton caching");
println!(" requires the generated singleton store)\n");
println!("2. Transient scope (#[injectable(scope = \"transient\")]):");
let handler1 = container
.resolve::<RequestHandler>()
.await
.expect("resolve RequestHandler");
let handler2 = container
.resolve::<RequestHandler>()
.await
.expect("resolve RequestHandler");
println!(" Each resolution creates a fresh instance");
println!(" handler1: {handler1:?}");
println!(" handler2: {handler2:?}\n");
println!("3. Transient scope via #[injectable_impl(scope = \"transient\")]:");
let p1 = container
.resolve::<TransientProcessor>()
.await
.expect("resolve TransientProcessor");
let p2 = container
.resolve::<TransientProcessor>()
.await
.expect("resolve TransientProcessor");
let p3 = container
.resolve::<TransientProcessor>()
.await
.expect("resolve TransientProcessor");
println!(" Processor IDs: #{}, #{}, #{}", p1.id, p2.id, p3.id);
println!(" Each gets a unique ID — fresh instance per resolution\n");
println!("4. Scope validation with DependencyGraph:");
let graph = injectable_rs_graph::DependencyGraph::new(vec![
injectable_rs_graph::GraphNode::with_scope("RequestHandler", &["Database"], "transient"),
injectable_rs_graph::GraphNode::leaf_with_scope("Database", "singleton"),
]);
let result = graph.validate();
println!(
" transient -> singleton: {}",
if result.is_ok() { "VALID" } else { "INVALID" }
);
let graph = injectable_rs_graph::DependencyGraph::new(vec![
injectable_rs_graph::GraphNode::with_scope(
"SingletonService",
&["TransientDep"],
"singleton",
),
injectable_rs_graph::GraphNode::leaf_with_scope("TransientDep", "transient"),
]);
let result = graph.validate();
println!(
" singleton -> transient: {}",
if result.is_ok() {
"VALID"
} else {
"INVALID (scope mismatch)"
}
);
println!("\n=== Example Complete ===");
}