1
1
package dix
2
2
3
3
import (
4
- "reflect"
5
-
6
4
"github.com/pubgo/dix/dixinternal"
7
5
"github.com/pubgo/funk/assert"
8
6
)
@@ -28,41 +26,220 @@ func New(opts ...Option) Container {
28
26
return dixinternal .New (opts ... )
29
27
}
30
28
31
- // Inject 执行依赖注入
29
+ // Inject 注入函数
32
30
//
33
- // container: 依赖注入容器
34
- // target: 注入目标 <*struct> 或 <func>
35
- // opts: 可选配置
36
- func Inject [T any ](container Container , target T , opts ... Option ) T {
37
- vp := reflect .ValueOf (target )
38
- if vp .Kind () == reflect .Struct {
39
- assert .Must (container .Inject (& target , opts ... ))
40
- } else {
41
- assert .Must (container .Inject (target , opts ... ))
42
- }
43
- return target
31
+ // 解析函数参数并调用函数。
32
+ // 通常用于启动函数或回调函数的依赖注入。
33
+ //
34
+ // 参数:
35
+ // - container: 依赖注入容器
36
+ // - fn: 目标函数,必须是函数类型
37
+ // - opts: 注入选项(可选)
38
+ //
39
+ // 函数注入规则:
40
+ // - 函数只能有入参,不能有出参
41
+ // - 函数参数类型必须在容器中已注册
42
+ // - 支持的参数类型:
43
+ // - 指针类型:*T
44
+ // - 接口类型:interface{}
45
+ // - 结构体类型:struct{}
46
+ // - 切片类型:[]T(注入所有匹配的实例)
47
+ // - 映射类型:map[string]T(注入带名称的实例)
48
+ // - 不支持基本类型参数:string, int, bool 等
49
+ // - 支持可变参数:func(handlers ...Handler)
50
+ //
51
+ // 函数限制:
52
+ // - 函数不能有返回值(包括 error)
53
+ // - 函数参数不能是基本类型
54
+ //
55
+ // 错误处理:
56
+ // - 参数解析失败时返回详细错误信息
57
+ // - 函数调用 panic 会被捕获并转换为错误
58
+ // - 如果函数有返回值,注册时会被拒绝
59
+ //
60
+ // 示例:
61
+ //
62
+ // // 有效的启动函数
63
+ // func StartServer(logger Logger, db *Database, handlers []Handler) {
64
+ // // 使用注入的依赖启动服务器
65
+ // }
66
+ //
67
+ // // 有效的回调函数
68
+ // func ProcessRequest(ctx Context, service *UserService) {
69
+ // // 处理请求
70
+ // }
71
+ //
72
+ // // 无效的函数(有返回值)
73
+ // func InvalidFunc(logger Logger) error {
74
+ // return nil // 不允许有返回值
75
+ // }
76
+ //
77
+ // // 无效的函数(基本类型参数)
78
+ // func InvalidFunc2(name string, port int) {
79
+ // // 不允许基本类型参数
80
+ // }
81
+ //
82
+ // // 使用示例
83
+ // container := dix.New()
84
+ // container.Provide(NewLogger)
85
+ // container.Provide(NewDatabase)
86
+ // container.Provide(NewUserService)
87
+ //
88
+ // // 注入并调用启动函数
89
+ // err := dix.Inject(container, StartServer)
90
+ // if err != nil {
91
+ // log.Fatal(err)
92
+ // }
93
+ func Inject (container Container , fn interface {}, opts ... Option ) error {
94
+ return container .Inject (fn , opts ... )
44
95
}
45
96
46
97
// Provide 注册依赖提供者
47
98
//
48
- // container: 依赖注入容器
49
- // provider: 提供者函数
99
+ // 支持的提供者函数签名:
100
+ // - func() T - 简单提供者
101
+ // - func() (T, error) - 带错误处理的提供者
102
+ // - func(dep1 D1, dep2 D2) T - 带依赖的提供者
103
+ // - func(dep1 D1, dep2 D2) (T, error) - 带依赖和错误处理的提供者
104
+ //
105
+ // 支持的输出类型:
106
+ // - 指针类型:*T
107
+ // - 接口类型:interface{}
108
+ // - 结构体类型:struct{}
109
+ // - Map类型:map[K]V
110
+ // - Slice类型:[]T
111
+ // - 函数类型:func(...)
112
+ //
113
+ // 不支持的类型:
114
+ // - 基本类型:string, int, bool 等(请使用指针类型替代)
115
+ //
116
+ // 错误处理:
117
+ // - 当提供者函数返回 (T, error) 时,如果 error 不为 nil,提供者调用失败
118
+ // - 错误会被包装并包含提供者类型和位置信息
119
+ // - 提供者注册失败时会 panic(使用 assert.Must)
120
+ //
121
+ // 示例:
122
+ //
123
+ // // 简单提供者
124
+ // dix.Provide(container, func() *Database {
125
+ // return &Database{Host: "localhost"}
126
+ // })
127
+ //
128
+ // // 带错误处理的提供者
129
+ // dix.Provide(container, func() (*Config, error) {
130
+ // config, err := loadConfig()
131
+ // if err != nil {
132
+ // return nil, fmt.Errorf("failed to load config: %w", err)
133
+ // }
134
+ // return config, nil
135
+ // })
136
+ //
137
+ // // 带依赖的提供者
138
+ // dix.Provide(container, func(config *Config) (*Database, error) {
139
+ // db, err := sql.Open("postgres", config.DatabaseURL)
140
+ // if err != nil {
141
+ // return nil, fmt.Errorf("failed to connect: %w", err)
142
+ // }
143
+ // return &Database{DB: db}, nil
144
+ // })
145
+ //
146
+ // 参数:
147
+ // - container: 依赖注入容器
148
+ // - provider: 提供者函数
50
149
func Provide (container Container , provider any ) {
51
150
assert .Must (container .Provide (provider ))
52
151
}
53
152
54
153
// Get 获取指定类型的实例(泛型版本)
55
154
//
56
- // container: 依赖注入容器
57
- // opts: 可选配置
155
+ // 支持获取的类型:
156
+ // - 单个实例:T(直接指定类型)
157
+ // - 切片:[]T(获取所有 T 类型的实例)
158
+ // - 映射:map[string]T(获取带名称的 T 类型实例)
159
+ //
160
+ // 类型解析规则:
161
+ // - 接口类型会匹配所有实现该接口的类型
162
+ // - 结构体类型精确匹配
163
+ // - 指针类型匹配对应的指针实例
164
+ //
165
+ // 错误情况:
166
+ // - 类型未注册:返回 ErrTypeNotFound
167
+ // - 循环依赖:返回 ErrCircularDependency
168
+ // - 提供者调用失败:返回包装后的错误
169
+ //
170
+ // 示例:
171
+ //
172
+ // // 获取单个实例
173
+ // logger, err := dix.Get[Logger](container)
174
+ // if err != nil {
175
+ // log.Fatal(err)
176
+ // }
177
+ //
178
+ // // 获取切片
179
+ // handlers, err := dix.Get[[]Handler](container)
180
+ // if err != nil {
181
+ // log.Fatal(err)
182
+ // }
183
+ //
184
+ // // 获取映射
185
+ // databases, err := dix.Get[map[string]Database](container)
186
+ // if err != nil {
187
+ // log.Fatal(err)
188
+ // }
189
+ //
190
+ // 参数:
191
+ // - container: 依赖注入容器
192
+ // - opts: 可选配置
193
+ //
194
+ // 返回值:
195
+ // - T: 请求的实例
196
+ // - error: 获取失败时的错误信息
58
197
func Get [T any ](container Container , opts ... Option ) (T , error ) {
59
198
return dixinternal .Get [T ](container , opts ... )
60
199
}
61
200
62
201
// MustGet 获取指定类型的实例,失败时panic(泛型版本)
63
202
//
64
- // container: 依赖注入容器
65
- // opts: 可选配置
203
+ // 功能与 Get 相同,但在获取失败时会 panic 而不是返回错误。
204
+ // 适用于确信实例一定存在的场景,如应用启动阶段。
205
+ //
206
+ // 支持获取的类型:
207
+ // - 单个实例:T(直接指定类型)
208
+ // - 切片:[]T(获取所有 T 类型的实例)
209
+ // - 映射:map[string]T(获取带名称的 T 类型实例)
210
+ //
211
+ // 使用场景:
212
+ // - 应用启动阶段,确信依赖已正确注册
213
+ // - 测试代码中,简化错误处理
214
+ // - 配置阶段,依赖缺失应该立即失败
215
+ //
216
+ // 示例:
217
+ //
218
+ // // 获取单个实例(确信存在)
219
+ // logger := dix.MustGet[Logger](container)
220
+ //
221
+ // // 获取切片(可能为空)
222
+ // handlers := dix.MustGet[[]Handler](container)
223
+ //
224
+ // // 在应用启动中使用
225
+ // func main() {
226
+ // container := setupContainer()
227
+ //
228
+ // // 这些依赖必须存在,否则应用无法启动
229
+ // logger := dix.MustGet[Logger](container)
230
+ // db := dix.MustGet[*Database](container)
231
+ //
232
+ // startServer(logger, db)
233
+ // }
234
+ //
235
+ // 参数:
236
+ // - container: 依赖注入容器
237
+ // - opts: 可选配置
238
+ //
239
+ // 返回值:
240
+ // - T: 请求的实例
241
+ //
242
+ // 注意:失败时会 panic,请确保在适当的场景下使用
66
243
func MustGet [T any ](container Container , opts ... Option ) T {
67
244
return dixinternal .MustGet [T ](container , opts ... )
68
245
}
0 commit comments