C# 中的依赖注入模式

2023-10-29

依赖注入模式 – DI (*)
首先,“依赖注入模式”是一种软件设计模式。它被称为“模式”,因为它建议针对特定问题的低级特定实现。

该模式旨在解决的主要问题是如何创建“松散耦合”的组件。它通过将组件的创建与其依赖项分开来实现这一点。

此模式中有四个主要角色(类):

Client:客户端是一个组件/类,它想要使用另一个组件提供的服务,称为Service.
Service-Interface:服务接口是描述服务组件提供什么样的服务的抽象。
Service:Service组件/类根据服务接口描述提供服务。
Injector:是一个组件/类,其任务是创建客户端和服务组件并将它们组装在一起。
它的工作方式是 Client 依赖于 Service-Interface IService。Client 依赖于IService接口,但不依赖于 Service 本身。服务实现IService接口并提供客户需要的某些服务。Injector 创建Client和Service对象并将它们组合在一起。我们说注入器将服务“注入”到客户端。
基于注入方法的依赖注入类型
通常在文献 [1] 中,人们会发现他们提到了不同类型的依赖注入,根据将服务注入客户端的方法进行分类。我认为这不是一个重要的区别,因为效果总是相同的,即对服务的引用被传递给客户端,无论如何。但是,为了完整起见,让我们解释一下。

因此,依赖注入的类型有:

构造函数注入——注入在Client构造函数中完成
方法注入——注入是通过专用方法完成的
属性注入——注入是通过public属性完成的
Client不知道正在注入哪个服务,如果是Service1,Service2或Service3。这就是我们想要的,我们看到组件/类、、、Client和是“松散耦合的”。Service1Service2Service3

Client类现在更具可重用性和可测试性。此功能的一个典型用法是在生产环境Client中注入真实服务Service1,在测试Client中注入环境Service2,这是一个仅为测试而创建的 Mock 服务。

这种模式的好处
这种模式的好处是:

创建松散耦合的组件/类Client和Service
客户端不依赖或不了解服务,这使其更具可重用性和可测试性
允许不同开发人员/团队并行开发组件/类客户端和服务,因为它们之间的边界由IService接口明确定义
它简化了组件的单元测试
这种模式带来的缺点是:

更努力地规划、创建和维护界面
依赖注入器来组装组件/类
类似的模式
这种模式与 GoF 书籍 Strategy Pattern [2] 非常相似。类图实际上是相同的。区别在于意图:

依赖注入更像是结构模式,其目的是组装松散耦合的组件,一旦组装,它们通常在客户端生命周期内保持这种状态;尽管
策略模式是行为模式,其目的是为问题提供不同的算法,这些算法通常在客户端生命周期内可以互换。
依赖倒置原则 – DIP (**)
因此,“依赖倒置原则(DIP)”是一种软件设计原则。它被称为“原则”,因为它提供了有关如何设计软件产品的高级建议。

DIP 是 Robert C. Martin [5] 提出的以首字母缩写词 SOLID [3] 着称的五种设计原则之一。DIP 原则规定:

高级模块不应该依赖于低级模块。两者都应该依赖于抽象。
抽象不应该依赖于细节。细节应该取决于抽象。
解释是:

虽然高级原则谈到“抽象”,但我们需要将其转换为我们特定编程环境中的术语,在本例中为 C#/.NET。C# 中的抽象是通过接口和抽象类来实现的。当谈到“细节”时,原则意味着“具体实施”。
因此,基本上,这意味着 DIP 促进了 C# 中接口的使用,具体实现(低级模块)应该依赖于接口。
控制反转 – IoC (***)
同样,“控制反转 (IoC)”是软件设计原则。它被称为“原则”,因为它提供了有关如何设计软件产品的高级建议。

在传统编程中,自定义代码始终具有流控制并调用库来执行任务。
IoC 原则建议(有时)将控制流给予库(“框架”),库(“框架”)将调用自定义代码来执行任务。

当他们说“框架”时,他们的意思是为特定任务设计的专门的、任意复杂的可重用模块/库,并且自定义代码的编写方式使其可以与该“框架”一起使用。我们说“控制流是倒置的”,因为现在“框架”调用了自定义代码。

该框架在控制应用程序活动中扮演主程序的角色。程序的主要控制是倒置的,从你移到框架上。控制反转是使框架不同于库的关键部分([26])。

IoC 原则促进了实现常见场景的可重用“软件框架”的开发和使用。然后,编写特定问题的自定义代码并使其与“框架”一起工作以解决特定任务。

虽然 IoC 原则经常在紧随其后的 Dependency Injection Pattern (*) 的上下文中被提及,但它是一个更广泛的概念。例如,基于事件处理程序/回调方法的“UI 框架”也遵循 IoC 原则。更多解释参见[26]、[25]、[8]。

依赖注入模式 (*) 遵循这一原则,因为正常的传统方法是让客户端创建服务并建立依赖关系。这里控制是倒置的,即服务的创建和依赖的创建被委托给注入器,在这种情况下,注入器就是“框架”。

依赖注入容器 (****)
因此,“依赖注入容器(DI Container)”是一个软件模块/库,可以通过许多高级选项实现自动依赖注入。

在 IoC 原则 (***) 的术语中,DI Container 具有“框架”的作用,因此您经常会看到它被称为“ DI 框架”,但我认为“框架”这个词被过度使用了,它导致混乱(你有 ASP MVC 框架、DI 框架、实体框架等)。

通常在文献中,它被称为“ IoC Container ”,但我认为 IoC 原则 (***) 是比 DI 模式 (*) 更广泛的概念,这里我们将真正的 DI 模式实现放在一个大规模。因此,“DI Container”是一个更好的名称,但“IoC Container”这个名称非常流行,并且被广泛用于同一事物。

什么是DI容器
还记得 DI 模式 (*) 和 Injector 的作用吗?因此,DI Container 是一个高级模块/库,可同时充当许多服务的注入器。它可以大规模实现DI模式,具有许多高级功能。DI Containers 是一种非常流行的架构机制,许多流行的框架(例如 ASP MVC)计划并支持 DI Containers 的集成。

最受欢迎的 DI 容器是 Autofac [10]、Unity [15]、Ninject [16]、Castle Windsor [17] 等。

DI 容器功能
一个 DI Container 将提供的典型功能是:

注册映射。您需要告诉 DI 容器在抽象(接口)到具体实现(类)之间的映射,以便它可以正确注入正确的类型。在这里,您向容器提供其工作所需的基本信息。

管理对象范围和生命周期。您需要告诉容器它创建的对象将具有什么范围和生命周期。
典型的“生活方式”模式是:

Singleton:始终使用对象的单个实例。
Transient:每次创建对象的新实例时。
Scoped:这通常是每个隐式或显式定义的范围的单例模式。
例如,您需要告诉容器,您是否希望每次解析依赖项时都创建一个新对象,或者您是否希望应用单例模式。例如,单例可以是每个进程、每个线程或每个“用户定义的范围”。此外,您需要指定对象的所需生命周期。例如,您可以将每个进程的对象生命周期或对象生命周期配置为每个“用户定义的范围”,这意味着对象将在用户定义的范围结束时被释放。容器可以强制执行所有这些,只需要精确配置。

解决方法。这是创建和组装所需对象/类型的实际工作。容器创建特定类型的对象,解析所有依赖项,并将它们注入到创建的对象中。该方法以递归方式深入工作,直到解决所有依赖项。DI Container 通过使用反射和类似技术来解决依赖关系。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 中的依赖注入模式 的相关文章

  • 为什么我不能从对中返回 unique_ptr?

    为什么我不能从对中返回 unique ptr include
  • 试图使用加密来混淆我的项目打破了它

    我试图尝试不同的混淆选项 为了做到这一点 我首先尝试了加密货币 以下是我遵循的步骤 打开加密向导并选择一些选项 选择我的解决方案文件 完成向导后 我看到有些 Dll 被很好地混淆了 但我的项目现在无法构建 我注意到的两件事是 我的文件夹中有
  • Java字符串中的字符数[重复]

    这个问题在这里已经有答案了 可能的重复 Java 使用unicode上划线显示平方根时字符串的长度 https stackoverflow com questions 7704426 java length of string when u
  • 如何使用 ProtoGen 从 proto 文件生成结构

    我们一直在使用 protobuf net ProtoGen 从 proto 文件生成 C cs 文件 我们希望代替类来生成结构 例如 DataContract public struct Entity1 ProtoMember 1 publ
  • 将授权标头添加到 Web 参考

    我正在尝试向客户端的网络服务发出请求 我不知道客户端的底层平台 我使用 添加 Web 引用 在 Visual Studio 2010 中使用了客户端的 WSDL 并生成了我的代理类 称为 ContactService 我现在需要将如下所示的
  • 为什么我无法调试动态加载的程序集?

    我正在开发一个 Web API 项目 该项目使用内部模拟框架 允许拦截和修改来自控制器的响应 它使用 MEF 加载包含某些先决条件匹配时执行的代码的程序集 我知道这是正常工作的 因为我可以在响应中看到模拟已被执行 但由于某种原因我无法调试动
  • C 中的链表数组:初始化和插入?

    我需要创建一个链表数组 如图所示 这就是我到目前为止所做的 typedef struct Node int data struct Node next Node int main void Node link 5 for int q 0 q
  • bean 中的 Spring JavaConfig 属性未设置?

    我正在考虑将 Spring JavaConfig 与一些属性文件一起使用 但 bean 中的属性未设置 bean 中的属性未设置 这是我的网络配置 Configuration EnableWebMvc PropertySource valu
  • 生成范围 [min,max] 内的随机数 [重复]

    这个问题在这里已经有答案了 我正在使用 C 生成范围 min max 内的整数随机数 我在用 int random int int min int max return min rand max min 但我认为上面的代码适用于范围 min
  • 在 Java Web 应用程序中获取 DataSource 资源

    我的 context xml 文件中有以下资源标记
  • 使用 _Alignas 进行结构成员对齐

    我想知道以下问题 是新的吗 Alignas结盟 C11 中的说明符适用于结构成员吗 我一直假设这么多 但彻底阅读了 N1570 公开草案似乎表明对齐说明符不能 出现在一个说明符限定符列表 这就是我所期望的 如果得到支持的话 我已经读过几遍语
  • C++ 联合数组和变量?

    在C 中没有办法做这样的事情吗 union Scalar x y Scalar v 2 Where x v 0 and y v 1 既然您使用的是 C 而不是 C 并且它们具有相同的类型 为什么不直接将 x 设为对 v 0 的引用 将 y
  • 如何组合||条件语句中的运算符[重复]

    这个问题在这里已经有答案了 代替 if foo 1 foo 5 foo 9 我喜欢将它们组合起来 类似于以下内容 这不起作用 if foo 1 5 9 那可能吗 不幸的是不是 你最好的选择是创建一个扩展方法 public static bo
  • 在Framework 4.6项目中使用.net core DLL

    我已经在 net core 2 0 中构建了一个 DLL 现在我想在使用 net 4 6 1 框架的 WinForms 项目中使用它 我可以引用该 dll 但收到 System IO FileLoadException 表示找不到 Syst
  • Ant 类路径和 junit.jar

    我有一个 build xml 它允许我运行 junit 测试 这是相关部分
  • 是否可以编写一个在另一个 Windows 应用程序中选择文本时收到通知的 Windows 应用程序?

    我很好奇是否可以编写一个程序来监视我的文本选择 一种可能的用途是编写一个与编辑器 IDE 无关的代码格式化程序 应用程序 服务 P 启动并以某种方式挂接到窗口中 以便在任何窗口中选择文本时收到通知 启动其他一些应用程序 A 用户选择 A 中
  • char[length]初始化并处理

    我定义了一个字符数组 char d 6 如果我在以下方面有误 请纠正我 此时没有为变量分配内存d 现在我要初始化它 d aaaaa 这种初始化之后 就不需要释放内存了 它将自动完成 我怎么知道是否char 被初始化了吗 我正在寻找类似的模式
  • 使用反射 API 填充 Proto 中的地图字段

    我正在尝试编写一个模块 该模块将获取 Message Builder 和从字段名称到值的映射 并将用值填充构建器 一切正常 直到我遇到地图字段 使用 Proto3 我收到一条特定消息 我知道我可以执行该消息的字段 builder b put
  • C#:如何处理乱序 TCP 数据包?

    请有人解释一下如何处理乱序数据包 我使用原始套接字来捕获数据包 并在数据包到来时解析它们 但其中一些数据包的顺序错误 例如 ID 标志 16390 PSH ACK 16535 PSH ACK 16638 确认 16640 PSH ACK 1
  • 如何获取 EC2 实例的 CloudWatch 指标数据

    我想获取我的 EC2 实例的 Cloudmetrics 数据 以便我可以使用这些数据绘制图表并将其显示在我的 Android 设备上 我怎么做 有相同的示例程序或教程吗 提前致谢 这就是我正在做的 private static void f

随机推荐

  • python 关于文件操作——基础详细

    先看后赞 养成习惯 点赞收藏 人生辉煌 python 文件操作 文件读写 write read readlines readline 文件的相关操作 简单易懂 目录 1 文件操作 1 1 文件打开与关闭 1 1 1 打开文件 1 1 2 关
  • Unity3D的传送带和物体移动

    实现工厂流程的传送带传送物体的过程 包过一些基础的知识点 图片效果看原文 工程下载请看原文 https xygeng cn post 266 html 1 传送物体左右上下移动 gameObject transform Translate
  • sqlite3数据库交叉编译并移植到嵌入式开发环境步骤

    一 首先到http www sqlite org download html下载linux版本的源码 sqlite autoconf 3130000 tar gz 二 解压 tar xvzf sqlite autoconf 3130000
  • vue自定义指令---页面水印

    一些页面为了防止用户截图 可以添加水印 下面介绍以下思路 主要是创建一个新的节点作为水印 设置好水印的样式以后 再添加到目标节点上面去 水印 export default inserted el text let dom document
  • bootstrap导航栏鼠标移入展开

    bootstrap鼠标移入导航展开下拉菜单则加以下jq代码 function dropdown mouseover function this children a addClass show next ul addClass show d
  • 记录第一次部署streamlit应用

    网上相关教程很多 经过多方尝试 记录自己成功的方法 一 通过git将项目文件上传至github 参考教程 23条消息 部署项目到github Gao 的博客 CSDN博客 github部署项目 二 添加requirements 部署在Str
  • 计算机主机mac地址怎么查,怎么查看电脑的Mac地址

    第一种方法 利用dos命令查看Mac地址 1 点击 开始 菜单 在 搜索程序和文件 输入框 输入 cmd 会找到进入dos命令的cmd程序 然后回车 快捷方式 WIN R 在输入cmd 2 回车后 弹出命令符窗口 输入 ipconfig a
  • 技术积累 — Ellisys软件及抓包器用户使用指南

    一 前言 Ellisys号称是业界最先进的蓝牙 Wi Fi USB协议分析仪 支持低功耗蓝牙协议分析测试 支持蓝牙5低功耗以及Wi Fi的物联网应用 支持与原始频谱 UART SPI HCI 逻辑信号等同步的宽带蓝牙5低能耗BLE Wi F
  • [Linux]-进程间通信之消息队列

    目录 消息队列的概述 消息队列的API 1 获取系统唯一Key值 IPC键值 2 创建消息队列 2 1查看消息队列的一些Linux命令 2 2消息队列的创建 3 消息的发送以及定义 3 1 通过消息队列发送信息 4 信息的接收 5 通过消息
  • Codeforces Round #660 (Div. 2)1388C - Uncle Bogdan and Country Happiness (好题,条件判断,DFS)

    题目大意 国家有N个城市 1号城市为首都 有M个国民 每个国民都在首都工作 晚上返回家中 给定每个城市有多少国民居住 每个城市都有一个心情检测器 当国民经过城市时 心情检测器根据国民的心情加减1 但是心情检测器并不精确 所以要求你去判断在所
  • 汽车电子相关术语

    SOA SOA Service Oriented Architecture 面向服务的架构 是一种在计算机环境中设计 开发 部署和管理离散模型的方法 是由Garnter1996年提出的概念 将应用程序的不同功能单元 称为服务 进行拆分 并通
  • NeRF论文翻译笔记

    分享 NeRF神经辐射场理解 深兰深延AI的博客 CSDN博客 神经辐射场 githubNeRF总结 https github com yenchenlin awesome NeRF 目录 摘要 1 介绍 2 相关工作 2 1 神经三维形状
  • ModuleNotFoundError: No module named 'exceptions'

    ModuleNotFoundError No module named exceptions 意味着你在你的代码中尝试使用了一个名为 exceptions 的模块 但是你的程序运行环境中找不到这个模块 这可能是因为这个模块没有安装 或者是你
  • MPC学习记录

    参考 无人驾驶车辆模型预测控制 第二版 第四章详细学习 算法部分 总系学不废的博客 CSDN博客 控制 模型预测控制MPC08 01总结修正 105664978 哔哩哔哩 bilibiliMPC 3 常用车辆模型 MATLAB 无人驾驶车辆
  • 用python计算工程量_使用python计算vintage

    coding utf 8 Created on Mon Jan 14 18 57 19 2019 author hinnc importnumpy as npimportpandas as pd from pandas tseries of
  • Python爬虫实战

    在本篇博客中 我们将使用Scrapy框架完成一个入门爬虫程序 在命令行创建scrapy项目 首先在命令行进入PyCharm的项目目录 然后执行 scrapy startproject 项目名 如ScrapyExample 生产爬虫项目 会自
  • eclipse如何安装server

    在eclipse中想添加配置server的是否 发现Preference目录里并没有Server这个选项 也就是说 我们并没有办法新建服务器 所以要安装一个server 1 eclipse help Install New Software
  • Java获取当前电脑的ip地址

    import java net Inet4Address import java net InetAddress import java net UnknownHostException author guochao version 1 0
  • 一文玩转pytorch转onnx-tensorRT ——(A)onnx转tensorRT

    说明 onnx和tensorRT是分开的 onnx像是prototxt和weight的打包在一起的东西 所以由onnx转到tensorRT下 还需要让onnx能搜索到 或parsing 所对应的层 caffeparsing有注册自定义层的函
  • C# 中的依赖注入模式

    依赖注入模式 DI 首先 依赖注入模式 是一种软件设计模式 它被称为 模式 因为它建议针对特定问题的低级特定实现 该模式旨在解决的主要问题是如何创建 松散耦合 的组件 它通过将组件的创建与其依赖项分开来实现这一点 此模式中有四个主要角色 类