依赖性注入是一种技术,它允许我们注入一个特定类的依赖对象,而不是直接创建这些实例。

使用依赖注入的好处显而易见,它通过放松模块间的耦合,来增强系统的可维护性和可测试性。

依赖注入允许我们修改具体实现,而不必改变依赖于它们的依赖类型。

ASP.NET Core 很重视依赖注入技术。ASP.NET Core 中内置的依赖注入提供功能模块,并不像 StructureMap 和 Ninject 等IoC(控制反转)容器那样功能丰富,但它速度快,易于配置,而且易于使用。我们可以使用它在 ASP.NET Core 中注入框架服务和应用程序服务。

关于依赖注入和控制反转的有关知识可以参考:设计模式

我们将介绍三种不同方法来解决 ASP.NET Core 6 中的依赖项。

本文中提供的代码示例均默认运行在 Visual Studio 2022。

1. 使用 VS2022 创建 ASP.NET Core 项目

我们在 Visual Studio 2022 中创建一个 ASP.NET Core 项目。按照以下步骤在 Visual Studio 2022 中创建一个新的 ASP.NET Core Web API 6 项目。

  • 1) 启动 Visual Studio 2022 IDE。
  • 2) 单击 “Create new project”。
  • 3) 在 “Create new project” 窗口中,从显示的模板列表中选择 “ASP.NET Core Web API”。
  • 4) 点击下一步。
  • 5) 在 “Configure your new project” 窗口中,指定新项目的名称和位置。
  • 6) 根据您的偏好,可选择选中 “Place solution and project in the same directory” 复选框。
  • 7) 点击下一步。
  • 8) 在接下来显示的 “Additional Information” 窗口中,从顶部的下拉列表中选择 .NET 6.0 作为目标框架。将 “Authentication Type” 保留为 “None”(默认)。
  • 9) 确保未选中 “Enable Docker,”、“Configure for HTTPS” 和 “Enable Open API Support” 复选框,因为我们不会在此处使用任何这些功能。您也可以选择取消选中 “Use controllers(取消选中以使用最少的 API)” 复选框,因为我们将创建自己的控制器。
  • 10) 单击创建。

这将在 Visual Studio 2022 中创建一个新的 ASP.NET Core 6 Web API 项目。我们将在本文的后续部分中使用该项目来说明解析依赖项。

2. 使用构造函数注入解决依赖关系

现在创建以下接口:

public interface ICustomFileLogger
{
public string Text { get; set; }
public void Log(string message);
}

为简单起见,我们给出一个最小的表示。

CustomFileLogger 类实现 ICustomFileLogger 接口,代码如下:

public class CustomFileLogger : ICustomFileLogger
{
public string Text { get; set; }
public void Log(string message)
{
// 自己的实现逻辑
}
}

如果使用的是 ASP.NET 5,可以在 ConfigureServices 方法中注册一个 ICustomFileLogger 类型的实例作为一个 Scoped 服务。如果使用的是 ASP.NET 6,则直接在 Program.cs 文件中注册。

services.AddScoped<ICustomFileLogger, CustomFileLogger>();

接下来,创建一个名为 DefaultController 的 API 控制器并输入以下代码:

[Route("api/[controller]")]
[ApiController]
public class DefaultController : ControllerBase
{
private ICustomFileLogger _logger;
public DefaultController(ICustomFileLogger logger)
{
_logger = logger;
if(string.IsNullOrEmpty(_logger.Text))
_logger.Text = DateTime.UtcNow.ToString();
}
[HttpGet]
public string Get()
{
return "Hello World!";
}
}

注意这里是如何使用构造函数注入的。DefaultController 类的构造函数接受 ICustomFileLogger 类型的实例作为参数。

3. 使用动作方法注入解决依赖关系

当需要在多个方法中使用注入的实例时,我们应该使用构造函数注入。如果只需要在特定的动作方法中使用实例,最好在动作方法中注入实例,而不是使用构造函数注入。

以下代码片段说明了如何实现动作方法注入。

[HttpPost("Log")]
public IActionResult Log([FromServices] ICustomFileLogger customFileLogger)
{
// 自己的实现逻辑
return Ok();
}

4. 使用 IServiceProvider 解决依赖关系

我们有时候可能经常需要在控制器中注入许多不同的服务。如果使用构造函数注入,则必须在构造函数中指定多个参数。所以,这种场景下,有一个更好的解决方案,就是使用 IServiceProvider。

我们可以使用 IServiceCollection 接口来创建依赖项注入容器。一旦创建了容器,IServiceCollection 实例就会组合成一个 IServiceProvider 实例。我们可以使用此实例来解析服务。

我们可以将 IServiceProvider 类型的实例注入到类的任何方法中。您还可以利用 IApplicationBuilder 接口的 ApplicationServices 属性和 HttpContext 类的 RequestServices 属性来检索 IServiceProvider 实例。

以下代码说明了如何注入 IServiceProvider 类型的实例:

public class DefaultController : Controller
{
private IServiceProvider _provider;
public DefaultController(IServiceProvider provider)
{
_provider = provider;
}
}

我们可以在操作方法中使用以下代码,来检索需要的任何服务实例。

ICustomFileLogger logger = (ICustomFileLogger)_provider.GetService(typeof(ICustomFileLogger));

注意 IServiceProvider 的 GetService 方法是如何用来检索服务实例的。

我们可以使用 HttpContext 类的 RequestServices 属性来检索 IServiceProvider 类型的实例,然后使用该实例调用 GetService 方法。

以下代码展示了HttpContext 类如何做到检索实例:

ICustomFileLogger logger = (ICustomFileLogger)HttpContext.RequestServices.GetService(typeof(ICustomFileLogger)); 
 

5. 总结

依赖性注入是一种通过放松耦合来增强代码维护和可测试性的方法。

我们可以使用 ASP.NET Core 中内置的依赖注入支持来创建模块化、精简和干净的应用程序,同时也使应用程序更容易维护和测试。

参考资料:

1. 设计模式

2. C#教程

如何解决 ASP.NET Core 中的依赖问题的更多相关文章

  1. ASP.NET Core中的依赖注入(1):控制反转(IoC)

    ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...

  2. ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理

    ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...

  3. ASP.NET Core中的依赖注入(2):依赖注入(DI)

    IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...

  4. ASP.NET Core中的依赖注入(3): 服务的注册与提供

    在采用了依赖注入的应用中,我们总是直接利用DI容器直接获取所需的服务实例,换句话说,DI容器起到了一个服务提供者的角色,它能够根据我们提供的服务描述信息提供一个可用的服务对象.ASP.NET Core ...

  5. ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【总体设计 】

    本系列前面的文章我们主要以编程的角度对ASP.NET Core的依赖注入系统进行了详细的介绍,如果读者朋友们对这些内容具有深刻的理解,我相信你们已经可以正确是使用这些与依赖注入相关的API了.如果你还 ...

  6. ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【解读ServiceCallSite 】

    通过上一篇的介绍我们应该对实现在ServiceProvider的总体设计有了一个大致的了解,但是我们刻意回避一个重要的话题,即服务实例最终究竟是采用何种方式提供出来的.ServiceProvider最 ...

  7. ASP.NET Core中的依赖注入(5):ServicePrvider实现揭秘【补充漏掉的细节】

    到目前为止,我们定义的ServiceProvider已经实现了基本的服务提供和回收功能,但是依然漏掉了一些必需的细节特性.这些特性包括如何针对IServiceProvider接口提供一个Service ...

  8. ASP.NET Core 中的依赖注入

    目录 什么是依赖注入 ASP .NET Core 中使用依赖注入 注册 使用 释放 替换为其它的 Ioc 容器 参考 什么是依赖注入 软件设计原则中有一个依赖倒置原则(DIP),为了更好的解耦,讲究要 ...

  9. ASP.NET Core 中的 依赖注入介绍

    ASP.NET Core 依赖注入 HomeController public class HomeController : Controller { private IStudentReposito ...

随机推荐

  1. Java秘诀!Java赋值运算符介绍

    运算符丰富是 Java 语言的主要特点之一,它提供的运算符数量之多,在高级语言中是少见的. Java 语言中的运算符除了具有优先级之外,还有结合性的特点.当一个表达式中出现多种运算符时,执行的先后顺序 ...

  2. Geocoding Tools(地理编码工具)

    地理编码工具 # Process: 创建地址定位器 arcpy.CreateAddressLocator_geocoding("", "", "&qu ...

  3. 洛谷3163 CQOI2014危桥 (最大流)

    一开始想了一发费用流做法然后直接出负环了 首先,比较显然的思路就是对于原图中没有限制的边,对应的流量就是\(inf\),如果是危桥,那么流量就应该是\(2\). 由于存在两个起始点,我们考虑直接\(s ...

  4. spring boot log4j2 最佳实践

    为什么选择 log4j2 Log4j2 使用了 LMAX Disruptor 库.在多线程场景中,异步 Logger 的吞吐量比 Log4j 1.x 和 Logback 高 18 倍,延迟低几个数量级 ...

  5. Redis使用过程中有哪些注意事项?看看BAT这类的公司是正确使用Redis的!!

    Redis使用过程中要注意的事项 Redis使用起来很简单,但是在实际应用过程中,一定会碰到一些比较麻烦的问题,常见的问题有 redis和数据库数据的一致性 缓存雪崩 缓存穿透 热点数据发现 下面逐一 ...

  6. ORB_SLAM3 -- 配置安装

    安装环境 Ubuntu20.04 ORB_SLAM3依赖项安装 opencv3 ORB_SLAM3可用opencv3或opencv4编译,作者这里安装测试了opencv3 Step1: 安装openc ...

  7. 技术博客--微信小程序canvas实现图片编辑

    技术博客--微信小程序canvas实现图片编辑 我们的这个小程序不仅仅是想给用户提供一个保存和查找的平台,还希望能给用户一个展示自己创意的舞台,因此我们实现了图片的编辑部分.我们对对图片的编辑集成了很 ...

  8. 晶振在电路设计时关于负载电容CL大小取值特别需要注意什么?

    在无源晶体的设计中,经常遇到负载电容CL的大小取值.晶振设计与精度的提高.KHz无源晶振的停止.音叉晶体谐振器的精度漂移以及精度和无源晶振在高温下的精度是否等于低温的精度烦忧的问题等. 无源晶体振荡器 ...

  9. The entitlements specified in your application’s Code Signing Entitlements file do not match those s

    今天给打包 TPshop IOS (搜豹商城) ipa文件 调试运行 xcode运行提示这个错误: The entitlements specified in your application's C ...

  10. 种类并查集(维护敌人的敌人是朋友)、并行-poj1182-食物链 笔记

    题意 输入若干组数据,代表着不同动物在食物链的位置(A,B,C),要求出在输入的过程中有多少组数据会与之前矛盾. 思路(借鉴挑战程序设计竞赛) 这题是学并查集时的题,所以用了并查集. 一开始我想的是, ...