提供一个通用的 Swift @Inject
属性包装器,可用于从您选择的依赖注入框架中注入对象/服务。
首先,您需要为您正在使用的依赖注入 (DI) 框架实现 Resolver
协议。
例如,当使用 Swinject 时
extension Container: InjectPropertyWrapper.Resolver {
}
对于 Swinject,Container
类已经包含一个具有相同签名 (resolve<T>(_ type: T, name: String?)
) 的方法,与 InjectPropertyWrapper Resolver
协议要求的一致。
然后,您需要设置全局解析器(例如在您的应用程序委托中)
let container = Container()
InjectSettings.resolver = container
在容器中注册一些对象
container.register(APIClient.self) { _ in APIClient() }
container.register(MovieRepository.self) { _ in IMDBMovieRepository() }
container.register(MovieRepository.self, name: "netherlands") { _ in IMDBMovieRepository("nl") }
现在您可以使用 @Inject
属性包装器在您自己的类中注入对象/服务
class IMDBMovieRepository: MovieRepository {
@Inject private var apiClient: APIClient
...
func fetchTop10(completionHandler: @escaping (movies: [Movie]) -> Void) {
...
}
}
class MovieViewModel: BindableObject {
public var didChange = PassthroughSubject<Void, Never>()
public private(set) var top10: [Movie]? {
didSet {
didChange.send()
}
}
@Inject private var movieRepository: MovieRepository
func load() {
movieRepository.fetchTop10() { [weak self] movies in
self?.top10 = movies
}
}
}
也可以使用 name 参数注入相同类型的不同对象
class MovieViewModel: BindableObject {
...
@Inject private var globalMovieRepository: MovieRepository
@Inject(name: "netherlands") private var nlMovieRepository: MovieRepository
...
}
通常,如果属性包装器无法解析依赖项,它将引发不可恢复的致命错误。如果由于某种原因,您希望某个对象有时在您的容器中不可用,您可以将该属性标记为可选
class MovieViewModel: BindableObject {
...
@Inject(name: "germany") private var deMovieRepository: MovieRepository?
...
}
要运行此包的测试,请确保 ENABLE_TESTS
环境变量设置为 1
或 true
。例如,当使用命令行时
ENABLE_TESTS=1 swift test
这允许包仅在测试时加载某些依赖项。
本项目采用 MIT 许可证条款。请参阅 LICENSE 文件。