aboutsummaryrefslogtreecommitdiff
path: root/examples/async-factory/main.rs
blob: 2b796ccafdf93f28c5c815e701ea0d62b1319b2c (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
#![deny(clippy::all)]
#![deny(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]

use std::time::Duration;

use anyhow::Result;
use syrette::future::BoxFuture;
use syrette::ptr::TransientPtr;
use syrette::AsyncDIContainer;
use tokio::time::sleep;

trait IFoo: Send + Sync
{
    fn bar(&self);
}

type IFooFactory =
    dyn Fn(i32) -> BoxFuture<'static, TransientPtr<dyn IFoo>> + Send + Sync;

struct Foo
{
    cnt: i32,
}

impl Foo
{
    fn new(cnt: i32) -> Self
    {
        Self { cnt }
    }
}

impl IFoo for Foo
{
    fn bar(&self)
    {
        for _ in 1..self.cnt {
            println!("Foobar");
        }
    }
}

trait IPerson: Send + Sync
{
    fn name(&self) -> String;
}

struct Person
{
    name: String,
}

impl Person
{
    fn new(name: String) -> Self
    {
        Self { name }
    }
}

impl IPerson for Person
{
    fn name(&self) -> String
    {
        self.name.clone()
    }
}

#[tokio::main]
async fn main() -> Result<()>
{
    let mut di_container = AsyncDIContainer::new();

    di_container.bind::<IFooFactory>().to_async_factory(&|_| {
        Box::new(|cnt| {
            Box::pin(async move {
                let foo_ptr = Box::new(Foo::new(cnt));

                foo_ptr as Box<dyn IFoo>
            })
        })
    })?;

    di_container
        .bind::<dyn IPerson>()
        .to_async_default_factory(&|_| {
            Box::new(|| {
                Box::pin(async {
                    // Do some time demanding thing...
                    sleep(Duration::from_secs(1)).await;

                    let person = TransientPtr::new(Person::new("Bob".to_string()));

                    person as TransientPtr<dyn IPerson>
                })
            })
        })?;

    let foo_factory = di_container
        .get::<IFooFactory>()
        .await?
        .threadsafe_factory()?;

    let foo_ptr = foo_factory(4).await;

    foo_ptr.bar();

    let person = di_container.get::<dyn IPerson>().await?.transient()?;

    println!("Person name is {}", person.name());

    Ok(())
}