How to use:
Cargo.toml
:
toml
waiter_di = "1.6.5"
lib.rs
or any other file, that uses library:
rust
use waiter_di::*;
See examples/1getstarted.rs for minimal example of usage.
See examples/2_modules.rs for example with modules and constructors.
See examples/3injectoptions_list.rs for the demo of all available injection options.
Annotate structure with #[component]
```rust
struct Comp {} ```
Annotate impl blocks with #[provides]
```rust
impl Interface for Comp {} ```
Create a container:
rust
fn main() {
let mut container = Container::<profiles::Default>::new();
}
Get dependency ref:
rust
fn main() {
let comp = Provider::<dyn Interface>::get(&mut container);
}
For Rc:
```rust
struct Dependency;
struct Comp {
dependency_rc: Rc
fn main() {
let mut container = Container::
to use Arc
instead of Rc
you need to add async
feature in cargo:
toml
waiter_di = { version = "...", features = [ "async" ] }
Also, you can use waiter_di::Wrc
type that will be compiled to Rc
or Arc
depending on async
feature.
To create new struct instead of getting reference:
```rust
struct Comp {
dependency: Dependency,
dependency_box: Box
fn main() {
let mut container = Container::
It uses config
crate under the hood, for example it tries to find float_prop
in args as --float_prop <value>
, if not found it tries to find it in environment variables,
after that tries config/{profile}.toml
, after that config/default.toml
```rust
struct ConfigObject { i32_prop: i32 }
struct Comp {
config: Config,
#[prop("int")] intprop: usize,
#[prop("int")] intpropopt: Option
Use Deferred type:
```rust
struct Comp {
dependencydef: Deferred
You can use predefined profiles from `waiter_di::profile" or create custom:
```rust struct CustomProfile;
impl Interface for Comp {}
fn main() {
let mut container = Container::
config/default.toml
Just define property named profile
as --profile <profile>
arg, profile
env variable or
profile
property in config/default.toml
and use inject!
macro:
rust
fn main() {
let comp = inject!(Comp: profiles::Default, profiles::Dev);
}
inject!
macro can't be used for several components, so it's recommended to use it with modules:
```rust
struct SomeModule { component: Component }
struct RootModule { somemodule: SomeModule } fn main() { let rootmodule = inject!(RootModule: profiles::Default, profiles::Dev); } ```
In this case #[module]
is just a synonym for #[component]
If you can't use #[component]
annotation, use factory function instead:
```rust
fn createdependency(boolprop: bool) -> Dependency { Dependency { prop: bool_prop } } ```
To use it like a constructor, use it with #[component]
on impl block:
```rust struct Comp();
impl Comp { #[provides] fn new() -> Self { Self() } } ```
Deferred
args in factory functions is unsupported. In the rest it can accept
the same arg types as #[component]
.
External types isn't supported for factory functions:
```rust
fn createexternaltype_dependency() -> HashMap
So you need to create crate-local wrapper:
```rust
struct Wrapper(HashMap
fn createexternaltype_dependency() -> Wrapper { Wrapper(HashMap::new()) } ```
For convenience, you can use #[wrapper]
attribute to implement Deref automatically:
```rust
struct HashMap(std::collections::HashMap
fn createexternaltype_dependency() -> HashMap {
return HashMap(std::collections::HashMap::