AnnotationInject 0.6.2

AnnotationInject 0.6.2

pjechris 维护。



 
依赖项
Sourcery>= 1.8.0
Swinject>= 0
 

  • 作者
  • pjechris

AnnotationInject

Cocoapods SPM tests twitter

生成您的依赖注入。旨在确保安全性。

AnnotationInject
🗽 让您从手动注册依赖中解脱出来。
将更多时间用于编码,而非配置时间!减少配置时间并专注于代码。
🛡 避免运行时崩溃,依赖项未更新。所有检查均在 编译时 完成。
👐 基于您喜欢的开源工具 SourcerySwinject 构建。
📖 100% 开源,受 MIT 许可证保护

特定版本的文档可能略有不同。如果您有任何问题,请首先检查发布的文档(通过在 Github 上选择分支/标签)。

注入问题的原因是什么?

没有注解

在使用依赖注入库(例如,Swinject)时,您需要 记住 注册您的依赖项

container.register(CoffeeMaker.self) { r in
  return CoffeeMaker(heater: r.resolve()!) // Trouble ahead, not sure Heater is in fact registered!
}

/// later in your code
let coffeeMaker = container.resolve(CoffeeMaker.self) // crash, missing Heater dependency!

运行这段代码可能会在 运行时 出现崩溃:我们没有注册任何 heater,导致 CoffeeMaker 解析器崩溃。

包含注解

注解将生成您的依赖,并确保所有内容在编译时都能解析。

/// sourcery: inject
class CoffeeMaker {
    init(heater: Heater) {

    }
}

这次我们会得到一个编译时错误,因为我们忘记声明一个 Heater 依赖。好极了!

使用方法

1. 注解您的依赖

/// sourcery: inject
class CoffeeMaker {
  init(heater: Heater) { }
}

/// sourcery: inject
class Heater {
    init() { }
}

2. 添加生成依赖的构建阶段

有关详细信息,请参阅安装

如果无法解析所有依赖项,则会失败构建阶段,阻止代码成功编译。

3. 添加生成的文件并使用生成的代码

let resolver = Assembler([AnnotationAssembly()]).resolver

// `registeredService` is generated code. It is completely safe at compile time.
let coffeeMaker = resolver.registeredService() as CoffeeMaker
let heater = resolver.registeredService() as Heater

安装

注意:AnnotationInject需要Sourcery来进行注解声明,Swinject作为依赖注入器。

  • Swift包管理器
dependencies: [
    .package(url: "https://github.com/pjechris/AnnotationInject.git", from: "0.6.0")
]

然后为您的项目添加一个构建阶段

swift run annotationinject-cli --sources <path to your sources> --output <path to output generated code> (--args imports=<MyLib1> -args imports=<MyLib2>>)
  • CocoaPods

pod AnnotationInject 添加到您的 Podfile 中并在项目中添加一个新的 构建阶段

"$(PODS_ROOT)"/AnnotationInject/Scripts/annotationinject --sources <path to your sources> --output <path to output generated code> (--args imports=<MyLib1> -args imports=<MyLib2>>)

注意:您可以将所有 sourcery 命令行选项传递给 annotationinject 脚本。

  • 手动操作
  1. 安装 SwinjectSourcery

  2. 复制粘贴源文件和模板文件夹,并在项目中添加一个新的 构建阶段

sourcery --templates <path to copied templates> --sources <path to your sources> --output <path to output generated code> (--args imports=<MyLib1> -args imports=<MyLib2>>)

可用注释

inject

将类注册到依赖注入容器中。

/// sourcery: inject
class CoffeeMaker { }
生成的代码

container.register(CoffeeMaker.self) {
  return CoffeeMaker()
}

extension SafeDependencyResolver {
  func registeredService() -> CoffeeMaker {
    return resolve(CoffeeMaker.self)!
  }
}

选项

name
为服务定义一个名称。生成的方法将使用该名称。
scope
参见 Swinject 对象作用域
type
定义阶级注册的类型。当您想对协议进行解析时使用它。

/// sourcery:inject: scope = "weak", type = "Maker", name = "Arabica"
class CoffeeMaker: Maker { }

inject (init)

为注入注册特定的 init。如果没有提供注解,则使用找到的第一个。

注意:类仍然需要 inject 注解。

// sourcery: inject
class CoffeeMaker {
  init(heater: Heater) { }

  // sourcery: inject
  convenience init() {
    self.init(heater: CoffeHeater())
  }
}
生成的代码

container.register(CoffeeMaker.self) {
  return CoffeeMaker()
}

extension SafeDependencyResolver {
  func registeredService() -> CoffeeMaker {
    return resolve(CoffeeMaker.self)!
  }
}

inject (attribute)

在 init 之后注入属性。属性需要被标记为可选 (?!)。

注意:类仍然需要 inject 注解。

// sourcery: inject
class CoffeeMaker {
  /// sourcery: inject
  var heater: Heater!

  init() { }
}
生成的代码

container.register(CoffeeMaker.self) {
  return CoffeeMaker()
}
.initCompleted { service, resolver in
  service.heater = resolver.registeredService()
}

provider

使用自定义函数来注册您的依赖项。这与手动实现 container.register 同时保持安全性相同。请注意,提供的方法 必须instantiate 中调用。

注意:如果您正在提供第三方库(例如来自 Cocoapods 的库),则需要将那些导入传递给 AnnotationInject,使用 args.imports MyLib,MyLib2,... 命令行参数。

class CoffeeMaker {
  init(heater: Heater) { }
}

// sourcery: provider
class AppProvider {
  static func instantiate(resolver: SafeDependencyResolver) -> CoffeeMaker {
    return CoffeeMaker(heater: CoffeHeater())
  }
}
生成的代码

container.register(CoffeeMaker, factory: AppProvider.instantiate(resolver:))

extension SafeDependencyResolver {
  func registeredService() -> CoffeeMaker {
    return resolve(CoffeeMaker.self)!
  }
}

provided(自 0.5.0 版本后不再需要)

将参数声明为参数,用于在解析方法中定义。在 init 和 provider 方法上工作。

注意事项

生成的代码由于缺少导入而无法编译

设置 --args imports=<MyLib1> -args imports=<MyLib2>>,以便生成的代码包含第三方库。

在生成的代码中,Foundation 类型(URLSession、NSNotificationCenter 等)为空(.self)

Sourcery 目前无法找到这些类型。因此,它们被视为不存在。解决方案:在 Provider 内部定义周围类型并为其提供 Foundation 类型。

构建阶段失败,没有错误报告

这可能是由于 Sourcery 与 Xcode 11.4 存在不兼容。解决方案:使用 Homebrew 安装 Sourcery 然后将 SOURCERY_BINPATH=sourcery 添加到构建步骤中的环境变量。

Pods/Sourcery/bin/Sourcery.app/Contents/MacOS/Sourcery:找不到文件或目录

您可能正在将 Sourcery 作为 Cocoapods 依赖项使用,但遗憾的是它并不总是工作得很好。解决方案:使用 Homebrew 安装 Sourcery,然后将 SOURCERY_BINPATH=sourcery 添加到构建步骤中的环境变量。

许可协议

本项目采用 MIT 许可证发布。请参阅 LICENSE 文件以获取详细信息。