核心是 Container类。它提供了两类方法,registerresolve

为了找到在 resolve 时,能够找到对应的方法,内部维护了一个叫做services 的字典。key 是根据 serviceTypenameargumentsType 确定的。
register 时,会字典里加入一个条目。在 resolve 时,会根据字典,找到对应的 ServiceEntryProtocol,然后调用其方法生成一个 component。

Container 类

register 方法

    public func _register<Service, Arguments>(
_ serviceType: Service.Type,
factory: @escaping (Arguments) -> Any,
name: String? = nil,
option: ServiceKeyOption? = nil
) -> ServiceEntry<Service> {
let key = ServiceKey(serviceType: Service.self, argumentsType: Arguments.self, name: name, option: option)
let entry = ServiceEntry(
serviceType: serviceType,
argumentsType: Arguments.self,
factory: factory,
objectScope: defaultObjectScope
)
entry.container = self
services[key] = entry behaviors.forEach { $0.container(self, didRegisterType: serviceType, toService: entry, withName: name) } return entry
}

如上所示,先生成了一个 ServiceKey,然后生成了一个 ServiceEntry,再把这两个值在字典里对应。

resolve 方法

var resolvedInstance: Service?
let key = ServiceKey(serviceType: Service.self, argumentsType: Arguments.self, name: name, option: option) if let entry = getEntry(for: key) {
resolvedInstance = resolve(entry: entry, invoker: invoker)
} if resolvedInstance == nil {
resolvedInstance = resolveAsWrapper(name: name, option: option, invoker: invoker)
}

即先生成一个 ServiceKey,然后根据这个 key 找到一个 ServiceEntry,然后根据这个 entry 和传入的方法,生成一个实例,返回。

ServiceKey

ServiceKey 是一个结构体,用来标识注册的一个服务。

// MARK: - ServiceKey
internal struct ServiceKey {
internal let serviceType: Any.Type
internal let argumentsType: Any.Type
internal let name: String?
} // MARK: Hashable
extension ServiceKey: Hashable {
var hashValue: Int {
return ObjectIdentifier(serviceType).hashValue
^ ObjectIdentifier(argumentsType).hashValue
^ (name?.hashValue ?? 0)
}
}

由于 ServiceKeynameserviceTypeargumentsType 都考虑在内了,所以下面两个注册,对应的是不同的 ServiceKey。 因为参数的类型不一样。
第一个参数类型是(String, Bool),第二个参数类型是 (Bool, String)。

container.register(Animal.self) { _, name, running in
Horse(name: name, running: running)
}
container.register(Animal.self) { _, running, name in
Horse(name: name, running: running)
}

ServiceEntry

ServiceEntry 实现了 ServiceEntryProtocol 方法,用来保存对应 ServiceKey 生产的实例,以及控制对象的范围(Object Scopes)。
在初始化时,会把 serviceTypeargumentsType、component 的构造方法factory 作为参数传递。
resolve时,如有必要会取出 ServiceEntryfactory,然后结合传过来的参数,调用 factory 生成一个 component(即实例)

let resolvedInstance = invoker(entry.factory as! Factory)

最新文章

  1. VS2010在空解决方案中添加项目
  2. Bzoj1115 石子游戏Kam
  3. SchemaExport的使用
  4. [转]ldconfig几个需要注意的地方
  5. Linux 和 Windows 下对long long的输出
  6. 尚学堂 JAVA DAY11 概念总结
  7. ASP.NET打印EXCEl报表技术总结
  8. 博士论文》》》 Journal,magazine,transaction,proceeding
  9. 自己动手写CPU之第八阶段(4)——转移指令实现过程2
  10. 腾讯云分布式高可靠消息队列服务CMQ架构
  11. Git错误一例
  12. 一张图看懂STM32芯片型号的命名规则
  13. Ambari 使用 Hive View 异常处理
  14. C# 获取变量或对象的栈与堆地址
  15. .net framework 项目 build 出现 未能加载文件或程序集“netfx.force.conflicts”或它的某一个依赖项
  16. Win10 1803 升级之后无法使用 共享目录的解决方法
  17. JavaScript——闭包机制
  18. post/get in console of JSarray/js 数组详细操作方法及解析合集
  19. PC客户端开发细节记录:保存GUID到VARIANT
  20. Building a Non-blocking TCP server using OTP principles

热门文章

  1. 13.11.20 jquery 核心 siblings() 获得同类(不包含自己)循环所有,
  2. 关闭文件流--fclose,
  3. 2018.10.14 bzoj4571: [Scoi2016]美味(主席树)
  4. hadoop学习笔记(五):java api 操作hdfs
  5. 理解指令的restrict属性(转)
  6. gj7 对象引用、可变性和垃圾回收
  7. (并查集 添加关系)How Many Answers Are Wrong --Hdu --3038
  8. Hdu1361&amp;&amp;Poj1068 Parencodings 2017-01-18 17:17 45人阅读 评论(0) 收藏
  9. SoC FPGA开发板的FPGA配置数据下载和固化
  10. windows下C++实现遍历本地文件