介绍

在阅读Visual code源码时发现有若干"@IContextKeyService"的代码,@后面紧跟需要注入的服务,一开始比较疑惑,不知道该对象是如何传入MenuItemAction的对象中的(实例化此类的时候并没有发现传入该对象),后面通过查询资料可知,这里使用依赖注入的方式注入contextKeyService对象,在软件工程中,依赖注入是被注入的对象接收其依赖的其他对象的技术。这些其他对象称为依赖项。在典型的“应用”关系中,接收对象称为客户端,而传递的(即“注入”)对象称为service。将服务传递给客户端的代码可以是各种东西需要自己定义,该工具称为注入器。注入程序会告诉客户端要使用的服务,而不是由客户端指定它将使用的服务。“注入”是指将依赖项(服务)传递给即将使用该依赖项的对象(客户端)。依赖项注入的目的是实现对象构造和使用关注点的分离。这可以提高可读性和代码重用。

依赖注入是控制反转(类似于好莱坞原则:不要打电话给我们,我们会打电话给您)的更广泛技术的一种形式。想要调用某些服务的客户端不必知道如何构造那些服务。相反,客户端将提供服务的责任委托给外部代码(注入程序)。不允许客户端调用注入器代码;构造服务的是注入器。然后,注入程序将服务注入(传递)到客户端中,该服务可能已经存在或可能由注入程序构造。然后,客户端使用服务。这意味着客户端不需要了解注入器,不需要知道如何构造服务,甚至不需要了解其正在使用的实际服务。客户端只需要知道服务的公共接口,因为它们定义了客户端如何使用服务。这可将“使用服务”的责任与“构建服务”的责任分开。

既然该技术拥有诸多优点,那能否在Python上实现它,并应用于自己的代码中呢?首先Google一下看看有没有现成的轮子(毕竟自己造轮子费时费力问题还多),通过Google找到Python上有一个依赖注入框架实现名为Injector。


export class MenuItemAction extends ExecuteCommandAction {readonly item: ICommandAction;readonly alt: MenuItemAction | undefined;private _options: IMenuActionOptions;constructor(item: ICommandAction,alt: ICommandAction | undefined,options: IMenuActionOptions,@IContextKeyService contextKeyService: IContextKeyService,@ICommandService commandService: ICommandService) {

安装

GitHub:https://github.com/alecthomas/injector

PyPI(可安装的,稳定的发行版):https://pypi.org/project/injector。您可以使用pip安装Injector:

pip install injector

官方文档:https://injector.readthedocs.io/en/latest/index.html

使用

通过一个小例子来简要说明injector组件的基本使用方法

测试代码:

from injector import Module, provider, Injector, inject, singleton, threadlocal
import sqlite3class IModelView(object):view = 'test'def __init__(self):passclass IRequestHandler(object):passclass Configuration(object):def __init__(self, connection_string):self.connection_string = connection_stringclass RequestHandler(IRequestHandler):@injectdef __init__(self, db: sqlite3.Connection, configuration: Configuration, my: 'MyClass'):self._db = dbself._configuration = configurationself.my = mydef get(self):cursor = self._db.cursor()cursor.execute('SELECT key, value FROM data ORDER by key')return cursor.fetchall()class MyClass:def __init__(self, value: int) -> None:self.value = valuedef factory():print('providing')return MyClass(42)def create_my_class(binder):configuration = Configuration(':memory:')binder.bind(Configuration, to=configuration, scope=threadlocal)binder.bind(MyClass, to=factory, scope=singleton)class DatabaseModule(Module):@singleton@providerdef provide_sqlite_connection(self, configuration: Configuration) -> sqlite3.Connection:conn = sqlite3.connect(configuration.connection_string)cursor = conn.cursor()cursor.execute('CREATE TABLE IF NOT EXISTS data (key PRIMARY KEY, value)')cursor.execute('INSERT OR REPLACE INTO data VALUES ("hello", "world")')return connclass ModelView(IModelView):view = 'test1'@injectdef __init__(self, req: IRequestHandler, my: MyClass):self.req = reqself.my = myinjector = Injector([create_my_class, DatabaseModule()], auto_bind=False)handler = injector.create_object(RequestHandler)
injector.binder.bind(IRequestHandler, handler)model_view = injector.create_object(ModelView)
injector.binder.bind(IModelView, model_view)

1. 创建injector对象,Injector内部将会获取模块并实例化对应的类,这里会创建MyClass的对象,并与MyClass类进行绑定;创建sqlitbinge3.Connection的对象,并与sqlite3.Connection类绑定;创建Configuration的对象,并与Configuration类绑定;

injector = Injector([create_my_class, DatabaseModule()])

2. 通过injector对象的create_object方法实例化RequestHandler,在RequestHandler中的构造函数上使用@inject注解,将在实例化过程中注入db(sqlitbinge3.Connection对象)、configuration(Configuration对象)、my(MyClass对象)注:这里使用Python3的类型注解功能来标注构造函数参数的类型,注入器会根据类型去寻找对应的对象,如果该对象不存在将会抛出异常;此时将RequestHandler看作客户端,其余注入的对象均为不同的服务,客户端通过调用服务中的方法即可使用该服务中的特定功能。例:get方法中使用db服务的cursor方法获取数据库游标,通过获取到的游标执行特定的Sql语句,实现特定的功能。IRequestHandler类可看作RequestHandler类的接口,使用injector.binder.bind方法,将handler对象与IRequestHandler接口进行绑定,这样下一次即可通过@inject注解,注入RequestHandler对象;

class IRequestHandler(object):passclass RequestHandler(IRequestHandler):@injectdef __init__(self, db: sqlite3.Connection, configuration: Configuration, my: 'MyClass'):self._db = dbself._configuration = configurationself.my = mydef get(self):cursor = self._db.cursor()cursor.execute('SELECT key, value FROM data ORDER by key')return cursor.fetchall()handler = injector.create_object(RequestHandler)
injector.binder.bind(IRequestHandler, handler)

3. 通过injector对象的create_object方法实例化ModelView,在实例化过程中将会分别注入IRequestHandler、MyClass类型对应的对象。

class ModelView(IModelView):view = 'test1'@injectdef __init__(self, req: IRequestHandler, my: MyClass):self.req = reqself.my = mymodel_view = injector.create_object(ModelView)
injector.binder.bind(IModelView, model_view)

4. 如果分别有两个类A、B,如果A依赖于B,B依赖于A,应该如何注入对应的依赖呢?

Python injector 依赖注入框架使用相关推荐

  1. Android:dagger2让你爱不释手-基础依赖注入框架篇

    前言 dagger2的大名我想大家都已经很熟了,它是解决Android或java中依赖注入的一个类库(DI类库).当我看到一些开源的项目在使用dagger2时,我也有种匆匆欲动的感觉,因此就立马想一探 ...

  2. 深入浅出依赖注入框架Dagger2

    目录 目录 依赖注入 依赖注入实现的三种方式 1. 构造注入 2. 属性注入 3. 接口注入 Dagger2 Dagger2的引入 不带Module的Inject方式(Inject+Component ...

  3. 依赖注入框架 wire

    在上一篇文章当中我们讲到了项目的目录结构,大体上水平切分为了四层,然后再根据需要进行垂直切分,然后由于我们大量的使用到了接口和依赖注入的手段,所以在项目初始化的时候如果手动进行依赖关系的初始化会比较麻 ...

  4. Google Guice 一个轻量级的依赖注入框架

    1.美图 2.概述 2.1 背景 在做项目的时候,看见有段代码直接是使用Google Guice 注入了avaitor表达式. 2.1 官网 Github 主页:https://github.com/ ...

  5. 简述依赖注入框架 Hilt 的实现原理

    目录 结论 1.Application 注解 @HiltAndroidApp 注解生成的文件 代码的执行流程 2.对象的创建流程 build 一下,看一下生成的类: 对象初始化流程 ActivityC ...

  6. Google开源依赖注入框架-Guice指南

    持续坚持原创输出,点击蓝字关注我吧 作者:软件质量保障 知乎:https://www.zhihu.com/people/iloverain1024 之前发过一篇文章<浅谈依赖注入的实现>, ...

  7. Android神匕首—Dagger2依赖注入框架详解

    简介 Dagger-匕首,鼎鼎大名的Square公司旗下又一把利刃(没错!还有一把黄油刀,唤作ButterKnife) Dagger2 是一个Android依赖注入框架,由谷歌开发,最早的版本Dagg ...

  8. android组件浮动在activity上_Jetpack Hilt 依赖注入框架上手指南

    code小生 一个专注大前端领域的技术平台公众号回复Android加入安卓技术群 作者:LvKang-insist 链接:https://juejin.im/post/5efdff9d6fb9a07e ...

  9. 依赖注入框架Autofac学习笔记

    Autofac是一个轻量级的依赖注入框架,可以在这里面下载:http://code.google.com/p/autofac/downloads/list 要想了解什么是依赖注入,可以参考下这篇博客: ...

最新文章

  1. 二分法:二分查找(递归+非递归)实现
  2. 18桥图片_世界上第一台70米泵车,采用10桥底盘,泵送速度可达200m/h
  3. Java学习日志(四)
  4. iPhone 13系列将搭载A15芯片:相比前代性能提升20%
  5. 7z001怎么解压在安卓手机上面_安卓zip文件压缩RAR解压手机下载-安卓zip文件压缩RAR解压v1.0最新版下载...
  6. Margin 属性的一些边界情况说明 --转http://blog.csdn.net/ghj1976/article/details/4987686
  7. hdu Collect More Jewels
  8. 《高等数学》:推导第七版下册第十章第四节的“利用曲面的参数方程求曲面的面积“
  9. 人工智能基础知识入门
  10. TZOJ 3244 Happy YuYu's Birthday(数学几何)
  11. 高洛峰mysql_【干货】MySQL 安装与安全优化
  12. sideEffects导致的全局样式消失
  13. Python 数据分析——Matplotlib相关知识
  14. iOS WKWebView加载本地文件之权威解说
  15. 党政机关计算机工作室装修标准规定,机房建设标准及规范-20210711211357.docx-原创力文档...
  16. 计算机在智能交通系统中应用,浅议计算机技术在现代智能交通系统中的应用
  17. PDF转换成PPT软件的使用方法
  18. 用matlab打造的摩斯电码加解码器音频版,支持包括中文在内的任意字符
  19. 老司机 iOS 周报 #47 | 2018-12-10
  20. 【电源设计】08电源中电容大小的计算

热门文章

  1. 名帖05 吴叡 篆书《千字文》
  2. 一篇夯实一个知识点系列--python生成器
  3. 你不甘堕落,却又不思进取
  4. 当小明来到上海,会发生什么呢?
  5. 关于数据库调优,看这些就够了
  6. 2018-02-07 水仙花数与黄金比例分割
  7. 微信小程序仿input组件、虚拟键盘
  8. java计算机毕业设计基于ssm的少儿编程管理系统(源代码+数据库+Lw文档)
  9. HTML:用键盘实现元素的方向移动
  10. 视频融合平台EasyCVR电子地图增加鼠标悬停展示经纬度