核心是 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)

Swinject 源码框架(一):基本原理的更多相关文章

  1. Swinject 源码框架(二):循环依赖的解决

    可能存在循环依赖,比如 Parent 强制有 Child, Child 弱持有 Parent. 具体实现如下.Parent 初始化时,必须传入 Child,而 Child 初始化不必传入 Parent ...

  2. Swinject 源码框架(三):Object Scopes

    Object Scopes 指定了生成的实例在系统中是如何被共享的. 如何指定 scope container.register(Animal.self) { _ in Cat() } .inObje ...

  3. TVM源码框架安装方法

    TVM源码框架安装方法 本文提供如何在各种系统上从零构建和安装TVM包的说明.它包括两个步骤: 首先从C++代码中构建共享库(linux的libtvm.so,macOS的libtvm.dylib和wi ...

  4. TensorFlow源码框架 杂记

    一.为什么我们需要使用线程池技术(ThreadPool) 线程:采用“即时创建,即时销毁”策略,即接受请求后,创建一个新的线程,执行任务,完毕后,线程退出: 线程池:应用软件启动后,立即创建一定数量的 ...

  5. vue2源码框架和流程分析

    vue整体框架和主要流程分析 之前对看过比较多关于vue源码的文章,但是对于整体框架和流程还是有些模糊,最后用chrome debug对vue的源码进行查看整理出这篇文章.... 本文对vue的整体框 ...

  6. golang 移动应用例子 example/basic 源码框架分析

    条件编译 我们在源码中可以看到2个文件: main.go 和 main_x.go 这两个包名都是 package main , 都有 main 函数. 不会冲突么? 答案是不会的, main_x.go ...

  7. jQuery源码框架fn解读

    (function( window, undefined ){ var jQuery = (function(){ var jQuery = function( selector, context ) ...

  8. Jmeter源码框架

    首先jmeter框架入口类: NewDriver类(src/core/org/apache/jmeter/NewDriver.java) public static void main(String[ ...

  9. MJRefresh源码框架分析

    MJRefresh是一款非常优秀的刷新控件.代码简洁,优雅.今天有时间对源代码阅读了一下.对MJRefresh的宏观设计非常赞叹.所谓大道至简就是这样吧.   MJRefresh所采用的主要设计模式非 ...

随机推荐

  1. PTA第一次作业和第二次作业

    PTA的第一次作业第一题: #include <stdio.h> int main (void) { int grade,i,N ,a=0,b=0,c=0,d=0,e=0; printf( ...

  2. SQLALchemy--ORM框架

    SQLAlchemy 1.介绍 SQLAlchemy是一个基于Python实现的ORM框架.该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之便是:将类和对象转换成SQL,然后使用 ...

  3. 不用快捷键就能使用Eclipse的自动完成功能

    偶然间看到了这个,或许有和我一样不喜欢按 alt-/ 兄弟用得上.不用老去按那个 alt-/ 了,还是方便不少.         打开 Eclipse -> Window -> Perfe ...

  4. struts2 file

    JavaBean 中: private File[] pic; private String[] picContentType; private String [] picFileName; sett ...

  5. 20155319 2016-2017-2 《Java程序设计》第九周学习总结

    20155319 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 整合数据库 ==16.1.1 JDBC简介== JDBC全名Java DataBase Co ...

  6. HDU 3455 Leap Frog 2016-09-12 16:34 43人阅读 评论(0) 收藏

    Leap Frog Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  7. 团队合作项目—(GG队)

    团队展示 一.队名:GG 二.队员信息 队员 学号 叶尚文(队长) 3116008802 蔡晓晴 3216008808 杜婷萱 3216008809 龙剑初 3116004647 于泽浩 311600 ...

  8. C99 中 main 函数的写法

    今天在论坛看见有人讨论 C 语言中 main 函数的写法,看到结论才知道 main 函数的正确写法. 被老谭酸菜坑了这么多年,还是记录下吧,或许以后某天不搞 .net,回去折腾 C 语言了. 写法1: ...

  9. ASP.NET 中 <%= %> 与 <%: %> 的区别

    做个备忘 <%= %> 内容原封不动输出 <%: %> 对内容进行编码后输出 即:<%: str %> 等价于 <%= Html.Encode(str) %& ...

  10. Docker技术:在微软云Azure上使用K8S

    周末,受微软公司的邀请,参加微软主持的云容器培训会议,为参加培训的学院提供技术辅导,引导学员体验微软云端的DevOps实践. 说是辅导,实际上自己也学到了许多的内容,包括K8S集群.负载.Azure中 ...