1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
//! LRDI — Rust Dependency Injection Framework
//!
//! A dependency injection container for Rust inspired by
//! Microsoft.Extensions.DependencyInjection (MEDI).
//!
//! # Quick start
//!
//! ```rust
//! use rust_dix::*;
//! use std::sync::Arc;
//!
//! // Trait-based interface (recommended)
//! trait ILogger: Send + Sync {
//! fn log(&self, msg: &str);
//! }
//!
//! struct ConsoleLogger;
//! impl ILogger for ConsoleLogger {
//! fn log(&self, msg: &str) { println!("[LOG] {}", msg); }
//! }
//!
//! // Register as trait interface
//! let provider = ServiceCollection::new()
//! .singleton::<dyn ILogger>(|_| Arc::new(ConsoleLogger))
//! .build()
//! .unwrap();
//!
//! // Resolve as trait
//! let logger: Arc<dyn ILogger> = provider.get().unwrap();
//! logger.log("Hello");
//! ```
//!
//! # Keyed services (strategy pattern)
//!
//! ```rust
//! use rust_dix::*;
//! use std::sync::Arc;
//!
//! trait Strategy: Send + Sync { fn execute(&self) -> &'static str; }
//!
//! struct FastStrategy;
//! impl Strategy for FastStrategy { fn execute(&self) -> &'static str { "fast" } }
//!
//! struct SafeStrategy;
//! impl Strategy for SafeStrategy { fn execute(&self) -> &'static str { "safe" } }
//!
//! let provider = ServiceCollection::new()
//! .keyed_singleton::<dyn Strategy>("fast", |_| Arc::new(FastStrategy))
//! .keyed_singleton::<dyn Strategy>("safe", |_| Arc::new(SafeStrategy))
//! .build()
//! .unwrap();
//!
//! let fast: Arc<dyn Strategy> = provider.get_keyed("fast").unwrap();
//! assert_eq!(fast.execute(), "fast");
//! ```
//!
//! # Build-time validation
//!
//! LRDI validates dependencies during `build()` to catch errors early:
//!
//! ```rust
//! # use rust_dix::*;
//! # use std::sync::Arc;
//! # struct A;
//! # struct B;
//! // Circular dependency detection — factories resolve deps via `get_any`
//! // (the `get::<T>()` method requires `Self: Sized` and cannot be called
//! // on `&dyn IServiceResolver`).
//! let result = ServiceCollection::new()
//! .singleton(|r| {
//! let _b = r.get_any(std::any::type_name::<B>()); // A depends on B
//! Arc::new(A)
//! })
//! .singleton(|r| {
//! let _a = r.get_any(std::any::type_name::<A>()); // B depends on A → CIRCULAR!
//! Arc::new(B)
//! })
//! .build();
//!
//! assert!(result.is_err());
//! if let Err(RdiError::CircularDependency(cycle)) = result {
//! println!("Circular dependency detected: {}", cycle);
//! }
//! ```
//!
//! # Async support
//!
//! For services that require async initialization (e.g., database
//! connections, remote config loading), use `build_async()` and
//! the `async_*` registration methods. `build_async()` returns
//! `Arc<ServiceProvider>` so that `provider_arc()` is available for
//! async resolution:
//!
//! ```rust,ignore
//! use rust_dix::*;
//! use std::sync::Arc;
//!
//! struct DbPool { conn: String }
//!
//! async fn connect_to_db() -> DbPool {
//! // async connection setup...
//! DbPool { conn: "connected".into() }
//! }
//!
//! # async fn run() {
//! let provider = ServiceCollection::new()
//! .async_singleton(|_| Box::pin(async {
//! Arc::new(connect_to_db().await)
//! }))
//! .build_async()
//! .await
//! .unwrap();
//!
//! let pool: Arc<DbPool> = provider.get_async().await.unwrap();
//! # }
//! ```
//!
//! # Features
//!
//! - **Three lifetimes**: Singleton, Scoped, Transient
//! - **Keyed services**: multiple implementations of the same trait by key
//! - `keyed_singleton(key, factory)` — shared globally
//! - `keyed_scoped(key, factory)` — shared within scope
//! - `keyed_transient(key, factory)` — new instance each time
//! - **Constructor injection**: `#[derive(Inject)]` on structs
//! - **Attribute-based auto-registration**: `#[rust_dix::inject]` on structs or trait impls
//! - **Compile-time module scanning**: `#[rust_dix::module]` collects `register!()` declarations
//! - **Cross-DLL support**: named service registry for cdylib plugins
//! - **Layered containers**: child-first resolution via `ServiceProviderWrapper`
//! - **Build-time validation**: circular dependency detection during `build()`
//!
//! # Crate layout
//!
//! | Module | Description |
//! |--------|-------------|
//! | [`ServiceCollection`] | Register services with a builder API |
//! | [`ServiceProvider`] | The root DI container |
//! | [`Scope`] / [`ServiceScope`] | Scoped container (one per scope) |
//! | [`IServiceResolver`] | Resolution trait (implemented by `ServiceProvider` & `Scope`) |
//! | [`ServiceProviderWrapper`] | Child-first layered container |
//! | [`ServiceLifetime`] | Enum: Singleton, Scoped, Transient |
//! | [`IProvider`] | Unified trait for resolution + named registry |
//! | [`RdiError`] | Error types (includes `CircularDependency`) |
//!
//! # Proc-macros
//!
//! - `#[derive(Inject)]` — auto-generates constructor injection code
//! - `#[rust_dix::inject]` — auto-registration on structs or trait impls
//! - `#[rust_dix::module]` — compile-time module scanning
//! - `rust_dix::register!(...)` — declare services inside `#[rust_dix::module]`
// ── Core types (MEDI-inspired naming) ──
/// Service collection — register services, then call `.build()`.
///
/// Analogous to `IServiceCollection` in Microsoft.Extensions.DependencyInjection.
pub use ServiceCollection;
/// Built service provider — the root DI container (read-only after build).
///
/// 兼具 MEDI 中 `IServiceProvider` 与 root scope 双重身份:
/// - 作为 `IServiceProvider`:提供类型/键控/命名解析入口。
/// - 作为 root scope:从根直接解析 Scoped 服务时,实例在根内缓存复用,
/// 语义等同于在根 scope 内单例化。通过 [`ServiceProvider::scope`] 创建的子 Scope
/// 拥有独立的 scoped 缓存,不回退到根。
///
/// Analogous to `IServiceProvider` in MEDI.
pub use ServiceProvider;
/// Service descriptor containing registration metadata.
pub use ServiceDescriptor;
/// Service lifetime enum: [`Singleton`](ServiceLifetime::Singleton),
/// [`Scoped`](ServiceLifetime::Scoped), [`Transient`](ServiceLifetime::Transient).
pub use ServiceLifetime;
/// Core resolution trait. Both [`ServiceProvider`] and [`Scope`] implement this.
pub use IServiceResolver;
/// A scoped service provider — created via [`ServiceProvider::scope`].
///
/// Analogous to `IServiceScope` in MEDI.
pub use Scope;
/// Alias for [`Scope`] with MEDI-inspired naming (`IServiceScope`).
pub use Scope as ServiceScope;
/// Factory trait for creating independent scopes. Injectable into singleton
/// services that need on-demand scope creation (e.g., background workers).
pub use ScopeFactory;
/// Internal types used by the container.
pub use ;
/// Wrapper combining child + root provider with child-first resolution.
pub use ServiceProviderWrapper;
// ── Plugin / cross-DLL support ──
/// Unified trait for service resolution and named registry access.
pub use IProvider;
// ── Error types ──
/// Error types returned from service resolution.
pub use RdiError;
// ── Runtime registration ──
pub use ServiceRegistration;
/// Re-export of `inventory` so that `#[rust_dix::inject]` generated code
/// can call `rust_dix::inventory::submit!` without requiring downstream crates
/// to add `inventory` to their own `Cargo.toml`.
pub use inventory;
// ── Proc-macros ──
// `inject` is the attribute macro (placed on structs or trait impls).
// `register` is the function-like macro used inside `#[rust_dix::module]`.
pub use ;