### Rust: Running Example Projects Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Provides shell commands to execute the example projects included with the loso-inject library. These examples demonstrate the practical application of derive and attribute macros. ```shell # Run derive macro example car go run --example inject_derive # Run attribute macro example car go run --example inject_attribute ``` -------------------------------- ### Rust Complete Application Example with loso-inject Source: https://context7.com/liuzsen/loso-inject/llms.txt A comprehensive Rust application example demonstrating loso-inject's dependency injection capabilities. It showcases domain, service, infrastructure, and application layers, with explicit management of Config (Instance), ConsoleLogger (Transient), and SharedCounter (Singleton) dependencies. The example uses `TypeFactory` to set up dependencies and `produce()` to build the application, verifying singleton behavior. ```rust use std::sync::{Arc, atomic::{AtomicU32, Ordering}}; use loso_inject::{Inject, InjectSingleton, TypeFactory}; // === Domain Layer === struct Config { is_production: bool, } trait Service { fn run(&self); } // === Service Layer === trait Logger { fn log(&self, message: &str); } trait Counter { fn add_one(&self); } #[derive(Inject)] pub struct UserService { config: Config, // Instance: from context logger: L, // Transient: new instance counter: C, // Singleton: shared instance } #[derive(Inject)] pub struct OrderService { logger: L, counter: C, } impl Service for UserService { fn run(&self) { let mode = if self.config.is_production { "Production" } else { "Development" }; self.logger.log(&format!("{} mode UserService", mode)); self.counter.add_one(); } } impl Service for OrderService { fn run(&self) { self.logger.log("OrderService running"); self.counter.add_one(); } } // === Infrastructure Layer === #[derive(Inject)] pub struct ConsoleLogger; impl Logger for ConsoleLogger { fn log(&self, message: &str) { println!("[LOG] {}", message); } } #[derive(Clone, InjectSingleton)] pub struct SharedCounter { count: Arc, } impl Counter for SharedCounter { fn add_one(&self) { self.count.fetch_add(1, Ordering::SeqCst); } } // === Application Layer === #[derive(Inject)] struct Controller { service1: S1, service2: S2, } fn main() { // Type aliases for readability type UserSvc = UserService; type OrderSvc = OrderService; type App = Controller; // Setup: inject config and shared counter state let count = Arc::new(AtomicU32::new(0)); let factory = TypeFactory::new() .add_instance(Config { is_production: false }) .add_instance(count.clone()); // Produce the complete dependency tree let app: App = factory.produce(); // Run services - they share the same Counter (singleton) // but have separate Logger instances (transient) app.service1.run(); // Logs and increments counter app.service2.run(); // Logs and increments counter // Verify singleton behavior: both services used same counter assert_eq!(count.load(Ordering::SeqCst), 2); println!("Total operations: {}", count.load(Ordering::SeqCst)); } ``` -------------------------------- ### Singleton Lifecycle Example (Rust) Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Demonstrates the Singleton lifecycle using `#[derive(InjectSingleton)]`. This ensures a type is instantiated only once within a given injection context. ```rust #[derive(Clone, InjectSingleton)] pub struct CounterImpl { count: Arc, } ``` -------------------------------- ### Instance Lifecycle Example (Rust) Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Illustrates the Instance lifecycle by pre-injecting a concrete type instance using `TypeFactory::add_instance()`. This is typically used for configuration or shared resources. ```rust let config = Config { is_production: false }; let factory = TypeFactory::new().add_instance(config); ``` -------------------------------- ### Create Dependency Tree with TypeFactory (Rust) Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Illustrates creating a dependency injection tree using loso-inject's TypeFactory. This example shows how to pre-inject an instance and then produce a dependent type. ```rust use loso_inject::TypeFactory; fn main() { // Create TypeFactory and inject Config instance let factory = TypeFactory::new() .add_instance(Config { is_production: false }); // Generate complete dependency tree let _service: UserService = factory.produce(); println!("Dependency injection successful!"); } ``` -------------------------------- ### Transient Lifecycle Example (Rust) Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Shows the implementation of a Transient lifecycle for a type using `#[derive(Inject)]`. This ensures a new instance is created each time the type is depended upon. ```rust #[derive(Inject)] pub struct ConsoleLogger; ``` -------------------------------- ### Add loso-inject Dependency (Shell) Source: https://github.com/liuzsen/loso-inject/blob/master/README.md This command adds the loso-inject crate as a dependency to your Rust project using Cargo. Ensure you have Rust and Cargo installed. ```shell cargo add loso-inject ``` -------------------------------- ### Enable Dependency Injection with #[inject] Macro in Rust Source: https://context7.com/liuzsen/loso-inject/llms.txt The `#[inject]` attribute macro is applied to `impl` blocks to enable dependency injection. It facilitates custom initialization logic and handling of special fields like `PhantomData` by allowing the framework to call the `new()` constructor and inject dependencies. This is particularly useful for structs requiring custom setup or when dealing with generic types. ```rust use loso_inject::{Inject, TypeFactory}; use loso_inject_macros::inject; use std::marker::PhantomData; // Struct with PhantomData requires custom constructor struct Repository { _db: DB, phantom: PhantomData, } #[derive(Inject)] struct PostgresConnection; #[inject] impl Repository { // The framework calls new() and injects dependency parameters fn new(db: DB) -> Self { println!("Initializing Repository..."); Self { _db: db, phantom: PhantomData, } } } // Using #[default] attribute for default values struct CacheService { ttl_seconds: u32, max_entries: usize, } #[inject] impl CacheService { fn new(#[default] ttl_seconds: u32, #[default] max_entries: usize) -> Self { Self { ttl_seconds, max_entries } } } fn main() { let factory = TypeFactory::new(); // Repository with custom constructor let repo: Repository = factory.produce(); // CacheService with default values let cache: CacheService = TypeFactory::new().produce(); assert_eq!(cache.ttl_seconds, 0); // u32::default() assert_eq!(cache.max_entries, 0); // usize::default() } ``` -------------------------------- ### TypeFactory: Produce Dependencies with Instance and Transient Lifecycles in Rust Source: https://context7.com/liuzsen/loso-inject/llms.txt Demonstrates using `TypeFactory` to manage dependencies. It shows how to add an `Instance` (Config) and produce a struct (UserService) with a `Transient` dependency (ConsoleLogger) resolved via Rust's type system. ```rust use loso_inject::{Inject, TypeFactory}; // Define a configuration struct (no derive needed for Instance types) struct Config { is_production: bool, database_url: String, } // Define an injectable logger service #[derive(Inject)] pub struct ConsoleLogger; // Define a service that depends on Config and a generic Logger #[derive(Inject)] pub struct UserService { config: Config, // Instance: extracted from TypeFactory logger: L, // Transient: auto-generated via L::inject() } fn main() { // Create TypeFactory and inject the Config instance let factory = TypeFactory::new() .add_instance(Config { is_production: false, database_url: "postgres://localhost/mydb".to_string(), }); // Produce the complete dependency tree let service: UserService = factory.produce(); // service.config and service.logger are automatically injected println!("Production mode: {}", service.config.is_production); } ``` -------------------------------- ### Define Types for Injection (Rust) Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Demonstrates defining types and marking them for injection using loso-inject's derive macros. It shows how to define concrete types, transient types, and types with dependencies. ```rust use loso_inject::Inject; // Configuration class - concrete type, injected as Instance struct Config { is_production: bool, } // Logger service - Transient type, creates new instance for each dependency #[derive(Inject)] pub struct ConsoleLogger; // User service - depends on Config and Logger #[derive(Inject)] pub struct UserService { config: Config, // Extracted from TypeFactory's pre-injected instance logger: L, // Auto-generated via L::inject() } ``` -------------------------------- ### #[derive(InjectSingleton)]: Singleton Dependency Injection in Rust Source: https://context7.com/liuzsen/loso-inject/llms.txt Explains the `#[derive(InjectSingleton)]` macro for creating singleton types within an injection context. It demonstrates how types implementing `Clone` and marked with `InjectSingleton` are instantiated only once per context, ensuring shared state. ```rust use std::sync::{Arc, atomic::{AtomicU32, Ordering}}; use loso_inject::{Inject, InjectSingleton, TypeFactory}; // Singleton counter - only one instance per injection context #[derive(Clone, InjectSingleton)] pub struct Counter { count: Arc, } impl Counter { pub fn increment(&self) -> u32 { self.count.fetch_add(1, Ordering::SeqCst) } pub fn get(&self) -> u32 { self.count.load(Ordering::SeqCst) } } #[derive(Inject)] pub struct ServiceA { counter: C, } #[derive(Inject)] pub struct ServiceB { counter: C, } #[derive(Inject)] pub struct App { service_a: A, service_b: B, } fn main() { // Pre-inject the Arc for Counter's internal state let shared_count = Arc::new(AtomicU32::new(0)); let factory = TypeFactory::new() .add_instance(shared_count.clone()); type AppType = App, ServiceB>; let app: AppType = factory.produce(); // Both services share the SAME Counter instance (Singleton) app.service_a.counter.increment(); // Returns 0 app.service_b.counter.increment(); // Returns 1 assert_eq!(shared_count.load(Ordering::SeqCst), 2); println!("Final count: {}", app.service_a.counter.get()); // Prints: 2 } ``` -------------------------------- ### Rust: Derive Macro for Dependency Injection Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Demonstrates using the `#[derive(Inject)]` macro for defining types with automatic dependency injection. This method is suitable for standard structs and handles automatic resolution of dependencies and creation of objects via the TypeFactory. ```rust use loso_inject::Inject; // 1. Define concrete type (Instance) - no need to derive Inject struct Config { is_production: bool, } // 2. Define generic type (Transient) - use #[derive(Inject)] #[derive(Inject)] pub struct ConsoleLogger; // 3. Define dependent type - mix Instance and Transient #[derive(Inject)] struct UserService { config: Config, // Instance: extracted from TypeFactory's pre-injected instance logger: L, // Transient: calls L::inject() to auto-generate new instance } // 4. Other Transient types #[derive(Inject)] struct Logger; fn main() { // 5. Create TypeFactory and inject Config instance let factory = TypeFactory::new() .add_instance(Config { is_production: false }); // 6. Generate complete dependency tree let _svc: UserService = factory.produce(); } ``` -------------------------------- ### Rust: Attribute Macro for Custom Constructors Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Illustrates using the `#[inject]` attribute macro for types requiring custom constructors. This is useful when specific initialization logic or handling of special fields like PhantomData is needed. ```rust use loso_inject_macros::inject; struct AA { _b: B, phantom: std::marker::PhantomData, } #[inject] impl AA { // Framework automatically calls new() function and injects dependency parameters fn new(b: B) -> Self { println!("Creating AA instance"); Self { _b: b, phantom: std::marker::PhantomData, } } } ``` -------------------------------- ### #[derive(Inject)]: Automatic Transient Dependency Injection in Rust Source: https://context7.com/liuzsen/loso-inject/llms.txt Illustrates the `#[derive(Inject)]` macro for automatic transient dependency injection. It shows how types marked with `Inject` are automatically instantiated when depended upon, creating a new instance each time. ```rust use loso_inject::{Inject, TypeFactory}; // Simple injectable unit struct #[derive(Inject)] pub struct ConsoleLogger; impl ConsoleLogger { pub fn log(&self, message: &str) { println!("[LOG] {}", message); } } // Injectable struct with dependencies #[derive(Inject)] pub struct UserService { logger: L, // Generic type: auto-injected via Inject trait } #[derive(Inject)] pub struct OrderService { logger: L, } // Controller depending on multiple services #[derive(Inject)] pub struct AppController { user_service: U, order_service: O, } fn main() { let factory = TypeFactory::new(); // Full type specification for dependency resolution type UserSvc = UserService; type OrderSvc = OrderService; let controller: AppController = factory.produce(); // Each ConsoleLogger is a new instance (Transient lifecycle) controller.user_service.logger.log("User service initialized"); controller.order_service.logger.log("Order service initialized"); } ``` -------------------------------- ### Control Injection Behavior with Field Attributes in Rust Source: https://context7.com/liuzsen/loso-inject/llms.txt Field attributes in `loso-inject` provide granular control over how dependencies are injected. `#[inject(default)]` utilizes `Default::default()` for initialization, `#[inject(instance)]` resolves dependencies from the context (auto-inferred for concrete types), and `#[inject(instance_clone)]` clones dependencies from the context, enabling multiple services to share the same instance of a type. ```rust use loso_inject::{Inject, TypeFactory}; #[derive(Clone)] struct AppConfig { app_name: String, debug: bool, } #[derive(Inject)] struct ServiceOne { // instance_clone: allows multiple services to share the same Config #[inject(instance_clone)] config: AppConfig, } #[derive(Inject)] struct ServiceTwo { #[inject(instance_clone)] config: AppConfig, } #[derive(Inject)] struct MetricsService { // default: uses Default::default() for this field #[inject(default)] request_count: u64, #[inject(instance_clone)] config: AppConfig, } #[derive(Inject)] struct Application { service_one: S1, service_two: S2, metrics: M, } fn main() { let config = AppConfig { app_name: "MyApp".to_string(), debug: true, }; let factory = TypeFactory::new() .add_instance(config); type App = Application; let app: App = factory.produce(); // All services share the same cloned config assert_eq!(app.service_one.config.app_name, "MyApp"); assert_eq!(app.service_two.config.app_name, "MyApp"); assert_eq!(app.metrics.config.app_name, "MyApp"); // MetricsService request_count initialized to default (0) assert_eq!(app.metrics.request_count, 0); } ``` -------------------------------- ### Rust: `#[inject(instance)]` Field Attribute Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Explains the `#[inject(instance)]` attribute for extracting pre-injected instances from the context. It highlights constraints such as appearing only once and the optional nature for concrete type fields. ```rust #[derive(Inject)] struct UserService { config: Config, // No need for #[inject(instance)], framework auto-infers } ``` -------------------------------- ### Rust: `#[inject(default)]` Field Attribute Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Shows how to use the `#[inject(default)]` attribute to automatically initialize a field with its default value using `Default::default()`. This can be applied to both derive and attribute macro usage. ```rust #[derive(Inject)] struct MyStruct { #[inject(default)] count: u8, // equivalent to count: u8::default() } // Attribute macro usage #[inject] impl MyStruct { fn new(#[default] count: u8) -> Self { Self { count } } } ``` -------------------------------- ### Create Singleton Types with #[inject_singleton] Macro in Rust Source: https://context7.com/liuzsen/loso-inject/llms.txt The `#[inject_singleton]` attribute macro simplifies the creation of singleton types that require custom constructors. The type must implement the `Clone` trait to allow for instance cloning. The `#[instance_clone]` attribute within the constructor ensures that the same instance is reused across multiple injection points, optimizing resource usage. ```rust use loso_inject::TypeFactory; use loso_inject_macros::inject_singleton; #[derive(Clone)] struct DatabasePool { connection_string: String, pool_size: u8, } #[inject_singleton] impl DatabasePool { // #[instance_clone] allows the same instance to be used multiple times fn new(#[instance_clone] connection_string: String, #[instance_clone] pool_size: u8) -> Self { println!("Creating database pool (this only runs once)"); Self { connection_string, pool_size } } } fn main() { let factory = TypeFactory::new() .add_instance("postgres://localhost/db".to_string()) .add_instance(10_u8); let pool: DatabasePool = factory.produce(); assert_eq!(pool.connection_string, "postgres://localhost/db"); assert_eq!(pool.pool_size, 10); } ``` -------------------------------- ### Rust: `#[inject(instance_clone)]` Field Attribute Source: https://github.com/liuzsen/loso-inject/blob/master/README.md Details the `#[inject(instance_clone)]` attribute, which allows obtaining a clone of a pre-injected instance. This enables multiple dependencies to share the same instance without consuming it. ```rust #[derive(Inject)] struct MyService { #[inject(instance_clone)] config: Config, // Allows multiple services to share the same Config } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.