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
use FromAttr;
use TokenStream;
use Scope;
use ;
use crateStructOrFunctionAttr;
/// 单例过程宏
///
/// # 参数说明
/// - `name`: 单例名称,默认使用结构体名称(首字符小写)生成, 例如: `TestData` -> `testData`
/// - `eager_create`: 是否在初始化时立即创建实例(预加载)
/// - `condition`: 可选条件闭包或路径,用于控制此单例的 Provider 是否插入 Context 中
/// - `binds`: 绑定路径列表,一般来说这里可以填入结构体的动态实现
/// - `async`: 可选异步标记路径值,指定是否为异步单例(使用 `#[async]` 属性重命名)
/// - `auto_register`: 是否自动注册到容器(仅在启用 `auto-register` 特性时有效,默认为 `DEFAULT_AUTO_REGISTER`)
/// - `default`: 使用结构体实现 `Default` trait 将实例注入仓库中
///
/// # 辅助宏参数说明
/// `resource`
/// - `name`: 单例名称,优先级高
/// - `option`: 表示这个字段是可能找不到的,那么字段类型必须为 `Option<T>`
/// - `default`: 此字段需要保证实现了 `Default` trait,在构建实例时,此字段使用默认值
/// - `vec`: 保证获取到所有此类型的单例,应和 `name` 参数排斥, 字段类型应为 `Vec<T>`
/// - `map`: 保证获取到所有此类型的单例, 前提当前字段实现了 `Singleton` trait, 字段类型应为 `std::collections::HashMap<K, V>`
/// - `ref`: 引用类型, & T
///
/// # 示例
/// ```rust
/// use std::sync::Arc;
///
/// #[singleton(
/// name = "myDataImpl",
/// condition = test_condition,
/// binds = [Self::into_data],
/// )]
/// struct DataImpl {
/// #[resource(name = "testData")]
/// data: String,
/// /// 这里用的是字段名称去仓库找单例并注入 `more_data` -> `moreData`, 若是指定名称则不会这样处理
/// more_data: Option<Vec<u8>>,
/// }
///
/// trait Data {
/// fn call() -> &'static str;
/// }
///
/// impl Data for DataImpl {
/// fn call() -> &'static str {
/// "hello"
/// }
/// }
///
/// impl DataImpl {
///
/// fn into_data(self) -> Arc<dyn Data> {
/// Arc::new(self)
/// }
/// }
///
/// fn test_condition(cx: &ApplicationContext) -> bool {
/// !cx.contains_single_with_name::<i32>("5")
/// }
/// ```
///
/// Single instance process macro
///
/// # Parameter Description
/// - ` name `: singleton name, generated by default using the structure name (lowercase first character), for example: `TestData` -> `testData`
/// - 'eager_create': Whether to immediately create an instance (preloaded) during initialization
/// - ` condition `: Optional conditional closure or path, used to control whether the Provider of this singleton is inserted into the Context
/// - ` bindings `: a list of binding paths, usually where the dynamic implementation of the structure can be filled in
/// - ` async `: Optional asynchronous tag path value, specifying whether it is an asynchronous singleton (rename using the ` # [async] ` property)
/// - ` auto_register `: Whether it is automatically registered to the container (only valid when the ` auto register ` feature is enabled, default is ` DEFAULT_SUTD_RIGIST `)
/// - ` default `: Use a struct to implement the ` Default ` trait and inject instances into the repository
///
/// # Auxiliary Macro Parameter Description
/// `resource`
/// - ` name `: Single instance name, high priority
/// - ` option `: indicates that this field may not be found, so the field type must be ` Option<T>`
/// - ` default `: This field needs to ensure that the ` Default ` trait is implemented. When building instances, this field uses the default value
/// - ` vec `: Ensure to obtain all singleton of this type, which should be excluded from the ` name ` parameter, and the field type should be ` Vec<T>`
/// - ` map `: Ensure that all singleton instances of this type are obtained, provided that the current field implements the ` Singleton ` trait and the field type should be ` std:: collections: HashMap<K, V>`
/// - ref: Reference type,&T
///
/// # Example
/// ```rust
/// use std::sync::Arc;
///
/// #[singleton(
/// name = "myDataImpl",
/// condition = test_condition,
/// binds = [Self::into_data],
/// )]
/// struct DataImpl {
/// #[resource(name = "testData")]
/// data: String,
/// Here, the field name is used to search for a single instance in the warehouse and inject 'more_data' ->'moreData'. If a name is specified, it will not be processed in this way
/// more_data: Option<Vec<u8>>,
/// }
///
/// trait Data {
/// fn call() -> &'static str;
/// }
///
/// impl Data for DataImpl {
/// fn call() -> &'static str {
/// "hello"
/// }
/// }
///
/// impl DataImpl {
///
/// fn into_data(self) -> Arc<dyn Data> {
/// Arc::new(self)
/// }
/// }
///
/// fn test_condition(cx: &ApplicationContext) -> bool {
/// ! cx.contains_single_with_name::<i32>("5")
/// }
/// ```
/// Define a transient provider.
/// Define a single owner provider.