一个采用宏的自供给式依赖注入框架,适用于 Swift

swift-blade

Swift-blade 是一个基于宏的 Swift 依赖注入框架。

其创意在很大程度上借鉴了 Dagger

安装

Swift 包管理器

在你的 Package.swift 文件中声明 swift-blade 作为依赖项:

.package(url: "https://github.com/shackley/swift-blade", from: "0.1.0")

将 Blade 作为依赖项添加到你的目标:

.product(name: "Blade", package: "swift-blade")

用法

我们通过制作咖啡机来用 swift-blade 演示依赖注入。有关可编译和运行的完整示例代码,请参阅 swift-blade-example

声明依赖项

Swift-blade 负责初始化应用程序类的实例,并提供其依赖项。

向初始化程序添加 @Provider 属性将允许 swift-blade 在应用程序的依赖关系图中提供该类的实例。类的初始化程序的参数是其依赖关系。当需要该类的实例后,swift-blade 将获取所需的参数值并初始化该类。

class Thermosiphon: Pump {
    private let heater: Heater

    @Provider(of: Thermosiphon.self)
    init(heater: Heater) {
        self.heater = heater
    }

  ...
}

注意 基于初始化程序的 @Provider 必须通过 @Provider 属性的 of 参数指定其返回类型。

class CoffeeMaker {
    private let heater: Heater
    private let pump: Pump

    @Provider(of: CoffeeMaker.self)
    init(heater: Heater, pump: Pump) {
        self.heater = heater
        self.pump = pump
    }

    ...
}

满足依赖项

默认情况下,swift-blade 通过按上述方式初始化所请求类型的实例来满足每个依赖项。

但基于初始化程序的 @Provider 无法在任何地方使用:

  • 无法初始化协议。
  • 无法注释第三方库类。

对于这些情况,请使用静态 @Provider 函数来定义如何满足依赖项。函数的返回类型定义它满足的依赖项。

例如,只要需要 Heater,就会调用 provideHeater()

@Provider
static func provideHeater() -> Heater {
    ElectricHeater()
}

静态 @Provider 函数也可以具有其自己的依赖项。例如,由于 Thermosiphon 具有基于初始化程序的 @Provider,所以 Pump 的提供程序可以写为:

@Provider
static func providePump(pump: Thermosiphon) -> Pump {
    pump
}

这样,swift-blade 负责初始化 Thermosiphon,并且静态 @Provider 函数仅用于将其命名为类型 Pump

最后,所有 @Provider 必须属于一个模块。这些只是具有 @Module 属性的空枚举。模块必须通过 @Module 属性的 providers 参数声明具有基于初始化程序的 @Provider 的类。静态 @Provider 直接嵌入在模块中。