Dip
简介
Dip
是一个简单的依赖注入容器。
目标是尽可能简单,同时提供在其他平台上依赖注入容器通常具有的丰富功能。它受到.NET
的Unity Container和其他依赖注入容器的影响。
- 您首先创建一个
let container = DependencyContainer()
并向container
注册您的依赖项,通过使用container.register { MyService() as Service }
将一个协议或类型与一个factory
相关联。 - 然后,您可以使用该
DependencyContainer
调用container.resolve() as Service
来使用协议或类型解决一个实例。 - 您可以将Dip与Storyboard和Nib轻松结合使用。还有一个强大的代码生成器,可以帮助简化新组件的注册。
基本用法
import Dip
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// Create the container
private let container = DependencyContainer { container in
// Register some factory. ServiceImp here implements protocol Service
container.register { ServiceImp() as Service }
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Resolve a concrete instance. Container will instantiate new instance of ServiceImp
let service = try! container.resolve() as Service
...
}
}
更复杂的示例
import Dip
class AppDelegate: UIResponder, UIApplicationDelegate {
private let container = DependencyContainer.configure()
...
}
//CompositionRoot.swift
import Dip
import DipUI
extension DependencyContainer {
static func configure() -> DependencyContainer {
return DependencyContainer { container in
unowned let container = container
DependencyContainer.uiContainers = [container]
container.register(tag: "ViewController") { ViewController() }
.resolvingProperties { container, controller in
controller.animationsFactory = try container.resolve() as AnimatonsFactory
}
container.register { AuthFormBehaviourImp(apiClient: $0) as AuthFormBehaviour }
container.register { container as AnimationsFactory }
container.register { view in ShakeAnimationImp(view: view) as ShakeAnimation }
container.register { APIClient(baseURL: NSURL(string: "http://localhost:2368")!) as ApiClient }
}
}
}
extension DependencyContainer: AnimationsFactory {
func shakeAnimation(view: UIView) -> ShakeAnimation {
return try! self.resolve(withArguments: view)
}
}
extension ViewController: StoryboardInstantiatable {}
//ViewController.swift
class ViewController {
var animationsFactory: AnimationsFactory?
private let _formBehaviour = Injected<AuthFormBehaviour>()
var formBehaviour: AuthFormBehaviour? {
return _formBehaviour.value
}
...
}
文档与用法示例
Dip 完全 有文档记录,并提供了一个游乐场,让您可以尝试其所有功能,并熟悉 API。您可以在 Dip.xcworkspace
中找到它。
注意:在使用游乐场之前,您可能需要先构建 Dip 框架。为此请选择
Dip
方案,并为 iPhone 模拟器构建。
您可以在 维基百科 中找到一个示例用法和一些有用的提示。
如果您正在使用 VIPER 架构 - 这里 是一个 VIPER 示例应用程序,它使用 Dip 而不是手动依赖注入。
还有一些博客文章描述了如何使用 Dip 以及其一些实现细节。
如果您有任何疑问,请提交一个问题。也欢迎大家提出拉取请求。
特性
- 作用域。Dip 支持 5 种不同的作用域(或生命周期策略):Unique、Shared、Singleton、EagerSingleton、WeakSingleton;
- 自动接线 & 自动注入。Dip 可以推断您的组件的构造函数中注入的依赖项,并自动解决它们以及用属性注入的依赖项。
- 解决可选值。Dip 可以解决构造函数或属性依赖项中定义的可选值。
- 类型转发。您可以注册同一工厂来解决单个类实现的多个类型的依赖。
- 循环依赖。如果您遵循一些简单的规则,Dip 将能够解决循环依赖关系;
- Storyboards 集成。您可以轻松地将 Dip 与 Storyboards 和 Xibs 一起使用,而无需在任何视图控制器代码中引用容器;
- 命名定义。您可以通过使用 标签 来注册对同一协议或类型的不同工厂进行注册;
- 运行时参数。您可以注册接受最多 6 个运行时参数的工厂(如果您需要可以扩展);
- 易于配置 & 代码生成。没有复杂的容器分级结构,没有不需要的功能。厌倦了手动编写所有注册信息?有一个 酷代码生成器 会为您创建它们。您唯一需要做的就是使用一些注释来标记您的代码。
- 弱类型组件。Dip 可以在编译时未知时解决“弱”类型。
- 线程安全。注册和解析组件是线程安全的;
- 有用的错误信息和配置验证。您可以对您的容器配置进行验证。如果在运行时无法解决的问题,Dip 会抛出一个完整描述问题的错误;
安装
您可以使用您喜欢的依赖管理器安装 Dip
CocoaPods
pod "Dip"
Carthage
github "AliSoftware/Dip"
要为 Swift 2.3 构建请使用 Carthage 并带有 --toolchain com.apple.dt.toolchain.Swift_2_3
选项。
Swift 包管理器
.Package(url: "https://github.com/AliSoftware/Dip", majorVersion: 5, minor: 0)
运行测试
在 OSX 上,您可以从 Xcode 中运行测试。在 Linux 上,您需要安装 Swift 包管理器,并使用以下命令使用它构建和运行测试: swift build --clean && swift build && swift test
鸣谢
此库由 Olivier Halligon 创建并由 Ilya Puchka 维护。
Dip 在 MIT 许可证 下可用。有关更多信息,请参阅 LICENSE
文件。
此 README.md
文件顶部的动画 GIF 来自 这个食谱,该食谱由 Kevin & Amanda 的美味博客提供。去试一下这个食谱吧!
用作 SampleApp 启动画面和图标的图片由 Matthew Hine 提供,根据 CC-by-2.0 许可。