aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 4c9eec0a455d32c3b491da8c666d2570b3172ed3 (plain)
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

Syrette

Latest Version Documentation

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

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.