Wormer 2.2.0

Wormer 2.2.0

测试测试
Lang语言 SwiftSwift
许可证 MIT
发布最后发布2019年5月
SPM支持SPM

Antonio Bello维护。



Wormer 2.2.0

什么是Wormer?

Wormer是一个轻量级且简单的依赖注入框架,用Swift编写,并更新到了语言的4.2版本。

它自由地受到了Unity的启发,这是一个为.NET平台的开源DI容器(不要与Unity游戏引擎混淆)。

Wormer使用静态声明式方法将接口与其实现链接起来。一个接口通常是一个协议,但它也可以是一个基类,而一个实现是一个采用该接口的类或结构体,理想情况下,它也可以是任何采用接口协议的值类型。

依赖注入容器通过Injector类访问,该类公开一个default静态属性。如果你想知道,是的,它使用了单例模式。初始化器被声明为私有,以防止直接实例化。

如何使用它

将接口与其实现绑定

给定一个接口

protocol Interface {}

以及一个实现了该接口的类

final class Implementation : Interface {}

通过调用bind方法建立链接

Injector.default.bind(interface: Interface.self, toImplementation: Implementation.self, asSingleton: false, initializer: { Implementation() })

《asSingleton》属性指定,当设置为true时,应该创建单个实例并始终返回,模仿单例模式。如果设置为false,则在任何调用instance()时创建新实例(请参阅下面的说明)。

最后一个参数initializer是一个闭包,必须创建并返回实现类型的实例。请注意,此闭包在内部存储,因此维护强引用。

获取与接口绑定的实例

将接口绑定到实现后,通过调用instance(for:)方法获取新的(或单例情况下的缓存的)实例

let instance = Injector.default.instance(for: Interface.self)

还有instance(for:)的一个重载版本,它利用接口类型的类型推断

let instance: Interface = Injector.default.instance()

警告:两个实现都内部使用强制解包来将接口转换为实现。如果没有将接口绑定到实现,这将导致运行时异常。有一个更安全的方法可用,它不使用强制解包,而是返回一个可选值

public func safeInstance<P>(for interfaceType: P.Type) -> P?

注释

  • 接口只能绑定到一个实现
  • 一个实现可以被多个接口绑定

如何使用

绑定

通常在应用启动时进行,因此最佳位置可能是application(didFinishLaunchingWithOptions:)。我有种良好的习惯,不滥用该方法,因此我通常会创建一个外部结构(或枚举)并具有静态方法,用于完成所有初始化。

enum DependencyBuilder {
	static func build() {
		let injector = Injector.default

		/// 1
		injector.bind(interface: EventBus.self,
			toImplementation: EventBusImplementation.self, asSingleton: true) {
			EventBusImplementation()
		}
		let eventBus: EventBus = injector.instance()

		/// 2
		injector.bind(interface: NotificationGateway.self,
			toImplementation: NotificationGatewayImplementation.self, asSingleton: true) {
			NotificationGatewayImplementation(eventBus: eventBus)
		}

		/// 3
		injector.bind(interface: NearableProximityProvider.self,
			toImplementation: BrandedNearableProximityProvider.self, asSingleton: false) {
			BrandedNearableProximityProvider()
		}
	}
}

上述代码创建了三个绑定

  1. EventBus绑定到EventBusImplementation,启用单例
  2. NotificationGateway绑定到NotificationGatewayImplementation,启用单例。注意初始化器要求一个EventBus实例
  3. 《NearableProximityProvider》绑定到《BrandedNearableProximityProvider》,不使用单例模式,因此在每次调用 instance() 时都会创建一个新的实例。

获取实例

如前一段所述,通过使用 instance() 方法或其 instance(for:) 重载来获取绑定到接口的实例。

有 2 种方式可以注入依赖

  • 在初始化器中
  • 通过属性

在所有情况下,我通常更倾向于使用前者,除非无法定义新的初始化器——一个典型的例子是 UIViewController,其生命周期通常不在我们的控制范围内,以及用于实例化的初始化器。

初始化器注入

假设有一个类或结构体如下

struct SomeProvider {
	private var eventBus: EventBus
	init(eventBus: EventBus) {
		self.eventBus = eventBus
	}
}

它接受一个 EventBus 作为初始化参数。要创建一个实例

let eventBus: EventBus = Injector.default.instance()
let provider = SomeProvider(eventBus: eventBus)

属性注入

当无法创建初始化器时,那么在 Wormer 中,属性注入是唯一的替代方案,至少是一种选择。以下是如何实现它

class EventViewController : UIViewController /* NSViewController */ {
	private lazy var eventBus: EventBus = Injector.default.instance()
}

EventViewController()

如您所见,我更喜欢延迟初始化,以确保仅在需要时才进行实例化。

安装

支持的平台

  • iOS: 支持
  • macOS: 目前不支持
  • watchOS: 目前不支持
  • tvOS: 目前不支持

Cocoapods

pod `wormer`

Carthage

抱歉,目前不可用(求帮助!!)

手册

复制 Wormer.swift 文件并将其粘贴到您的项目中。

许可

MIT 许可。阅读 LICENSE 文件。