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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
//! # How to use
//!
//! ### Basics
//!
//! * PortalDI handle a dependency as a field (constructor injection). Dependencies must be specified as `DI<T>`.
//!
//! * Depencency types must implement `DITarget` and be thread safe.
//! * Traits must be DITarget.
//! ```
//! use portaldi::*;
//! trait MyTrait: DITarget { }
//! ```
//! * Structs automatically become DITarget when its fileds are `Send + Sync`.
//!
//! * In PortalDI, components are handled as singleton and with lazy initioalization by default.
//! * If a component must be initialized in advance, you can explicitly call `di` method in where you want.
//! * If a component must be prototype (1 instance by 1 ref), you can annotate with `prototype`.
//!
//! ### Structs dependencies
//!
//! When a dependency is a struct, you can simply annotate on a target.
//! The PortalDI's macro generates DIPortal implementation for a target struct.
//!
//! ```
//! use portaldi::*;
//!
//! #[derive(DIPortal)]
//! struct Hoge {
//! foo: DI<Foo>, // FooProvider must be in this scope
//! // other deps
//! }
//!
//! #[derive(DIPortal)] // DIPortal implementation and FooProvider are generated.
//! struct Foo { /* other deps */ }
//!
//! // Use component
//! Hoge::di();
//!
//! ```
//!
//!
//! ### Trait object dependencies
//!
//! When a dependency is a trait object, you can annotate a target struct with a `provide` attribute.
//! The PortalDI's macro generates DIPortal implementation for the target struct and DIProvider implementation for the trait.
//! The dependent struct's scope must have the depencency DIProvider.
//!
//! ```
//! use portaldi::*;
//!
//! #[derive(DIPortal)]
//! struct Hoge {
//! foo: DI<dyn FooI>, // FooIProvider must be in this scope.
//! // other deps
//! }
//!
//! pub trait FooI: DITarget {}
//!
//! #[derive(DIPortal)]
//! #[provide(FooI)]
//! struct Foo { /* other deps */ }
//!
//! impl FooI for Foo {}
//!
//! // Use component
//! Hoge::di();
//! // Use FooI component
//! FooIProvider::di();
//!
//! ```
//!
//! ### Manually component creation
//!
//! When you need a custom creation logic for a compoonent, you manually define a implementation for `DIPortal`.
//!
//! #### For struct type depencency
//!
//! ```
//! use portaldi::*;
//!
//! #[derive(DIPortal)]
//! struct Hoge {
//! foo: DI<Foo>, // FooProvider must be in this scope
//! // other deps
//! }
//!
//! pub struct Foo { /* other deps */ }
//!
//! #[provider(Self)]
//! impl DIPortal for Foo {
//! fn create_for_di(container: &DIContainer) -> Self {
//! // custom creation logic
//! Foo {}
//! }
//! }
//!
//! // Use component
//! Hoge::di();
//!
//! ```
//!
//! #### For trait object depencency
//! If a depencency is a trait object and has custom creation logic, you can annotate `provider` on a `DIPortal` implementation.
//!
//! ```
//! use portaldi::*;
//!
//! #[derive(DIPortal)]
//! struct Hoge {
//! foo: DI<dyn FooI>, // FooIProvider must be in this scope
//! // other deps
//! }
//!
//! pub trait FooI: DITarget {}
//!
//! struct Foo { /* other deps */ }
//!
//! impl FooI for Foo {}
//!
//! #[provider(FooI)]
//! impl DIPortal for Foo {
//! fn create_for_di(container: &DIContainer) -> Self {
//! // custom creation logic
//! Foo {}
//! }
//! }
//!
//! // Use component
//! Hoge::di();
//!
//! ```
//!
//! #### For async creation logic
//! If a depencency has async custom creation logic, you manually define a implementation for `AsyncDIPortal`.
//! Also you need anotate `inject` with `async` on the depencency field.
//!
//! ```
//! use portaldi::*;
//! use async_trait::async_trait;
//!
//! #[derive(DIPortal)]
//! struct Hoge {
//! #[inject(async)]
//! foo: DI<Foo>, // FooProvider must be in this scope
//! // other deps
//! }
//!
//! pub struct Foo { /* other deps */ }
//!
//! #[provider(Self)]
//! #[async_trait]
//! impl AsyncDIPortal for Foo {
//! async fn create_for_di(container: &DIContainer) -> Self {
//! // custom creation logic
//! Foo {}
//! }
//! }
//!
//! async {
//! // Use component
//! Hoge::di().await;
//! };
//!
//! ```
//!
//! #### For complex creation logic that involves other components.
//! If a depencency has custom creation logic that needs other components, you manually define a factory component and implementation for `DIPortal`.
//!
//! ```
//! use portaldi::*;
//! use async_trait::async_trait;
//!
//! #[derive(DIPortal)]
//! struct Hoge {
//! #[inject(async)]
//! foo: DI<Foo>,
//! // other deps
//! }
//!
//! pub struct Foo { /* other deps */ }
//!
//! #[provider(Self)]
//! #[async_trait]
//! impl AsyncDIPortal for Foo {
//! async fn create_for_di(container: &DIContainer) -> Self {
//! FooFactory::di_on(container).create().await
//! }
//! }
//!
//! #[derive(DIPortal)]
//! struct FooFactory {
//! bar: DI<Bar>,
//! // other deps
//! }
//!
//! impl FooFactory {
//! async fn create(&self) -> Foo {
//! // custom creation logic that needs a bar.
//! Foo {}
//! }
//! }
//!
//! #[derive(DIPortal)]
//! struct Bar { /* other deps */ }
//!
//! async {
//! // Use component
//! Hoge::di().await;
//! };
//!
//! ```
//!