Swinject 源码框架(一):基本原理

核心是 Container类。它提供了两类方法,register 和 resolve。
为了找到在 resolve 时,能够找到对应的方法,内部维护了一个叫做services 的字典。key 是根据 serviceType、name、argumentsType 确定的。
在 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)
}
}
由于 ServiceKey 把 name、serviceType、argumentsType 都考虑在内了,所以下面两个注册,对应的是不同的 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)。
在初始化时,会把 serviceType、argumentsType、component 的构造方法factory 作为参数传递。
在 resolve时,如有必要会取出 ServiceEntry 的 factory,然后结合传过来的参数,调用 factory 生成一个 component(即实例)
let resolvedInstance = invoker(entry.factory as! Factory)
Swinject 源码框架(一):基本原理的更多相关文章
- Swinject 源码框架(二):循环依赖的解决
可能存在循环依赖,比如 Parent 强制有 Child, Child 弱持有 Parent. 具体实现如下.Parent 初始化时,必须传入 Child,而 Child 初始化不必传入 Parent ...
- Swinject 源码框架(三):Object Scopes
Object Scopes 指定了生成的实例在系统中是如何被共享的. 如何指定 scope container.register(Animal.self) { _ in Cat() } .inObje ...
- TVM源码框架安装方法
TVM源码框架安装方法 本文提供如何在各种系统上从零构建和安装TVM包的说明.它包括两个步骤: 首先从C++代码中构建共享库(linux的libtvm.so,macOS的libtvm.dylib和wi ...
- TensorFlow源码框架 杂记
一.为什么我们需要使用线程池技术(ThreadPool) 线程:采用“即时创建,即时销毁”策略,即接受请求后,创建一个新的线程,执行任务,完毕后,线程退出: 线程池:应用软件启动后,立即创建一定数量的 ...
- vue2源码框架和流程分析
vue整体框架和主要流程分析 之前对看过比较多关于vue源码的文章,但是对于整体框架和流程还是有些模糊,最后用chrome debug对vue的源码进行查看整理出这篇文章.... 本文对vue的整体框 ...
- golang 移动应用例子 example/basic 源码框架分析
条件编译 我们在源码中可以看到2个文件: main.go 和 main_x.go 这两个包名都是 package main , 都有 main 函数. 不会冲突么? 答案是不会的, main_x.go ...
- jQuery源码框架fn解读
(function( window, undefined ){ var jQuery = (function(){ var jQuery = function( selector, context ) ...
- Jmeter源码框架
首先jmeter框架入口类: NewDriver类(src/core/org/apache/jmeter/NewDriver.java) public static void main(String[ ...
- MJRefresh源码框架分析
MJRefresh是一款非常优秀的刷新控件.代码简洁,优雅.今天有时间对源代码阅读了一下.对MJRefresh的宏观设计非常赞叹.所谓大道至简就是这样吧. MJRefresh所采用的主要设计模式非 ...
随机推荐
- 《JavaScript DOM编程艺术》笔记
1. 把<script>标签放到HTML文档的最后,<body>标签之前能使浏览器更快地加载页面. 2. nodeType的常见取值 元素节点(1) 属性节点(2) 文本节点( ...
- Ckeditor上传图片返回的JS直接显示出来,未执行!!!
Ckeditor上传图片网上有很多教程. 下面是我今天下午遇到的一个坑...自己挖的坑. 在conotroller里 我开始习惯性的 response.setContentType("app ...
- 用org.mybatis.generator 生成代码
1:引入pom 2:增加生成配置xml: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...
- ViewFlipper实现自动播放的图片库
作者实现的基础上,加上了文字的变换 public class MainActivity extends Activity { private ViewFlipper viewFlipper; priv ...
- UVa 111 History Grading (简单DP,LIS或LCS)
题意:题意就是坑,看不大懂么,结果就做不对,如果看懂了就so easy了,给定n个事件,注意的是, 它给的是第i个事件发生在第多少位,并不是像我们想的,第i位是哪个事件,举个例子吧,4 2 3 1, ...
- python 实现排列组合
1.python语言简单.方便,其内部可以快速实现排列组合算法,下面做简单介绍. 2.一个列表数据任意组合 2.1主要是利用自带的库 #_*_ coding:utf-8 _*_ #__author__ ...
- ArcGIS Desktop Python add-ins 插件类型
Python可以在ArcGIS 桌面程序中创建如下的插件类型: 插件类型 描述 按钮(button) 是一个简单功能定制形式,可以在点击情况下执行一些业务逻辑.它会执行一个或一系列的动作.按钮可以放在 ...
- 顺序表[A+B->C]
/*----代码段@映雪------*/ /*采用顺序表存储,改成数组也行*/ int MergeList(SeqList &A,SeqList &B,SeqList &C) ...
- C++和Python混合编程
为何人工智能(AI)首选Python?读完这篇文章你就知道了:https://blog.csdn.net/qq_41769259/article/details/79419322 C++调用Pytho ...
- (回文串 Manacher )Girls' research -- hdu -- 3294
http://acm.hdu.edu.cn/showproblem.php?pid=3294 Girls' research Time Limit:1000MS Memory Limit:32 ...