测试已测试 | ✓ |
语言语言 | SwiftSwift |
许可证 | MIT |
发布日期最后发布日期 | 2017年10月 |
SwiftSwift版本 | 3.0 |
SPM支持SPM | ✓ |
由Aryan Ghassemi维护。
Swift的依赖项容器
模块文件是你定义依赖项的地方。目标是抽象出这个文件中的所有依赖项。应该只有项目中的模块类知道具体实现,而你的应用中的其余类应通过接口使用这些实现。
你可以有多个模块类来组织你的依赖项
public class AppModule: DIModule {
public func load(container: DIContainer) {
container.bind(type: URLSession.self) { URLSession.shared() }
container.bind(type: HttpService.self) { HttpClient(baseUrl: "https://api.github.com", urlSession: container.resolve(type: URLSession.self)) }
container.bind(type: GithubService.self) { GithubHttpClient(httpService: container.resolve(type: HttpService.self)) }
container.bind(type: UserDefaults.self, asSingleton: false) { UserDefaults.standard() }
container.bind(type: AnalyticsTracker.self, named: GoogleAnalyticsTracker.analyticsIdentifier()) { GoogleAnalyticsTracker() }
container.bind(type: AnalyticsTracker.self, named: AmplitudeAnalyticsTracker.analyticsIdentifier()) { AmplitudeAnalyticsTracker() }
}
}
class AppDelegate: UIResponder, UIApplicationDelegate {
override init() {
super.init()
DIContainer.instance.addModule(AppModule())
}
}
避免直接使用单例,以提高代码的可测试性
container.bind(type: URLSession.self) { URLSession.shared() }
不要在你的类中添加单例逻辑,只需将它们绑定为单例
注意:结构体与单例模式不兼容
// Bind class as singleton
bind(Session.self, asSingleton: true) { Session() }
// Bind protocol to an implementation as singleton
bind(AnalyticsTracker.self, asSingleton: true) { GoogleAnalyticsTracker() }
在存在多个单一协议实现的情况下,您可以使用名称绑定来检索正确的实例
bind(AnalyticsTracker.self, named: "Google") { GoogleAnalyticsTraker() }
bind(AnalyticsTracker.self, named: "Amplitude") { AmplitudeAnalyticsTracker() }
// Inject expected instance
let googleAnalyticsTracker: AnalyticsTracker = inject(named: "Google")
let amplitudeAnalyticsTracker: AnalyticsTracker = inject(named: "Amplitude")
// Get all implementations for a given protocol (great for chain of responssibilities)
let trackers: [AnalyticsTracker] = injectAll()
仅对根级别使用属性注入,对于viewController以下的任何内容都使用构造器注入
class ViewController: UIViewController {
let githubService: GithubService = inject() // Injects the implementation defined in module
let session = inject(Session.self) // injects the singleton instance
let analyticTrackers: [AnalyticsTracker] = injectAll() // Injects all implemetations of AnalyticsTracker
}
简单地将依赖项通过初始化程序传递,并在模块文件中定义绑定
protocol GithubService { }
protocol HttpService { }
class GithubHttpClient: GithubService {
let httpService: HttpService
// Constructor injection
init(httpService: HttpService) {
self.httpService = httpService
}
}
class AppModule: DIModule {
func load(container: DIContainer) {
container.bind(type: URLSession.self) { URLSession.shared() }
container.bind(type: HttpService.self) { HttpClient(baseUrl: "https://api.github.com", urlSession: container.resolve(type: URLSession.self)) }
container.bind(type: GithubService.self) { GithubHttpClient(httpService: container.resolve(type: HttpService.self)) }
}
}
class ViewController: UIViewController {
// Property Injection
// This will return an instance of GithubHttpClient with all depndencies as defined in module
let githubService: GithubService = inject()
}