di/
inject.rs

1use crate::{InjectBuilder, ServiceLifetime};
2
3/// Defines the behavior of an injectable type.
4pub trait Injectable: Sized {
5    /// Creates and returns a [builder](crate::InjectBuilder) for an injected type.
6    ///
7    /// # Arguments
8    ///
9    /// * `lifetime` - The [lifetime](crate::ServiceLifetime) of the injected type
10    fn inject(lifetime: ServiceLifetime) -> InjectBuilder;
11
12    /// Creates and returns a [builder](crate::InjectBuilder) for a singleton injected type.
13    fn singleton() -> InjectBuilder {
14        Self::inject(ServiceLifetime::Singleton)
15    }
16
17    /// Creates and returns a [builder](crate::InjectBuilder) for a scoped injected type.
18    fn scoped() -> InjectBuilder {
19        Self::inject(ServiceLifetime::Scoped)
20    }
21
22    /// Creates and returns a [builder](crate::InjectBuilder) for a transient injected type.
23    fn transient() -> InjectBuilder {
24        Self::inject(ServiceLifetime::Transient)
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31    use crate::*;
32
33    trait TestService {}
34    trait OtherTestService {}
35
36    #[derive(Default)]
37    struct TestServiceImpl {}
38    struct OtherTestServiceImpl {
39        _service: Ref<dyn TestService>,
40    }
41
42    impl TestService for TestServiceImpl {}
43
44    impl Injectable for TestServiceImpl {
45        fn inject(lifetime: ServiceLifetime) -> InjectBuilder {
46            InjectBuilder::new(
47                Activator::new::<dyn TestService, Self>(
48                    |_| Ref::new(Self::default()),
49                    |_| Ref::new(Mut::new(Self::default())),
50                ),
51                lifetime,
52            )
53        }
54    }
55
56    impl OtherTestServiceImpl {
57        fn new(service: Ref<dyn TestService>) -> Self {
58            Self { _service: service }
59        }
60    }
61
62    impl Injectable for OtherTestServiceImpl {
63        fn inject(lifetime: ServiceLifetime) -> InjectBuilder {
64            InjectBuilder::new(
65                Activator::new::<dyn OtherTestService, Self>(
66                    |sp| Ref::new(Self::new(sp.get_required::<dyn TestService>())),
67                    |sp| {
68                        Ref::new(Mut::new(Self::new(sp.get_required::<dyn TestService>())))
69                    },
70                ),
71                lifetime,
72            )
73        }
74    }
75
76    impl OtherTestService for OtherTestServiceImpl {}
77
78    #[test]
79    fn inject_should_invoke_constructor_injection() {
80        // arrange
81        let services = ServiceCollection::new()
82            .add(TestServiceImpl::singleton())
83            .add(OtherTestServiceImpl::transient())
84            .build_provider()
85            .unwrap();
86
87        // act
88        let service = services.get::<dyn OtherTestService>();
89
90        // assert
91        assert!(service.is_some());
92    }
93}