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 |
|
Syrette
The convenient dependency injection library for Rust.
Namesake
From the syrette Wikipedia article.
A syrette is a device for injecting liquid through a needle. It is similar to a syringe except that it has a closed flexible tube (like that typically used for toothpaste) instead of a rigid tube and piston.
Features
- A dependency injection container
- Autowiring dependencies
- API inspired from the one of InversifyJS
- Helpful error messages
- Enforces the use of interface traits
- Supports generic implementations & generic interface traits
- Binding singletons
- Detection and prevention of circular dependencies
Optional features
factory
. Binding factories (Rust nightly required)
To use these features, you must enable it in Cargo.
Motivation
Other DI libraries for Rust are either unmaintained (di for example), overcomplicated and or bloated (anthill-di for example) or has a weird API (teloc for example).
The goal of Syrette is to be a simple, useful, convenient and familiar DI library.
Example usage
use syrette::{injectable, DIContainer};
use syrette::ptr::TransientPtr;
trait IWeapon
{
fn deal_damage(&self, damage: i32);
}
struct Sword {}
#[injectable(IWeapon)]
impl Sword
{
fn new() -> Self
{
Self {}
}
}
impl IWeapon for Sword
{
fn deal_damage(&self, damage: i32)
{
println!("Sword dealt {} damage!", damage);
}
}
trait IWarrior
{
fn fight(&self);
}
struct Warrior {
weapon: TransientPtr<dyn IWeapon>,
}
#[injectable(IWarrior)]
impl Warrior
{
fn new(weapon: TransientPtr<dyn IWeapon>) -> Self
{
Self { weapon }
}
}
impl IWarrior for Warrior
{
fn fight(&self)
{
self.weapon.deal_damage(30);
}
}
fn main()
{
let mut di_container = DIContainer::new();
di_container.bind::<dyn IWeapon>().to::<Sword>();
di_container.bind::<dyn IWarrior>().to::<Warrior>();
let warrior = di_container.get::<dyn IWarrior>().unwrap();
warrior.fight();
println!("Warrior has fighted");
}
For more examples see the examples folder.
Todo
- Add support for generic factories
- Add asynchronous functionality
Contributing
You can reach out by joining the mailing list.
This is the place to submit patches, feature requests and to report bugs.