您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > .NET

ASP.NET Core依赖注入原理详解与Autofac库深度集成实践

时间:2023-06-15 12:56:46  来源:今日头条  作者:小乖兽技术

在ASP.NET Core中,依赖注入(DI)是非常重要的特性。本文将深入探讨ASP.NET Core源码中的容器IOC和依赖注入的实现原理。

什么是IoC

Inversion of Control(IoC)是指将控制权反转过来,即由系统来控制程序的执行流程。传统的程序都是由开发人员自己编写代码来控制程序的执行流程,而IoC则是将这种“主动权”交给了系统。

在IoC中,对象的创建和管理由框架或容器来完成,这些对象也被称为服务。应用程序通过请求获取服务,而不是直接创建服务对象。

什么是DI

Dependency Injection(DI)是IoC的一种具体实现方式。在DI中,服务提供方和服务使用方之间的耦合关系由第三方组件(DI容器)来处理。容器负责实例化服务,并将其注入到需要该服务的类中。

ASP.NET Core中的DI容器可以帮助我们解决应用程序中的对象管理问题,例如创建对象、管理对象的生命周期等。

ASP.NETCore DI容器的注册

在ASP.NET Core中,我们可以使用以下方法将服务注册到DI容器:

services.AddScoped<IMyService, MyService>();

其中,AddScoped方法将服务注册为Scoped生命周期,IMyService是服务接口,MyService是服务的实现。

ASP.NETCore DI容器的解析

在ASP.NET Core中,我们可以使用以下代码从DI容器中解析服务:

var service = serviceProvider.GetService<IMyService>();

其中,GetService方法从容器中解析出指定类型的服务对象,返回一个IServiceProvider类型的实例。

ASP.NETCore DI容器的生命周期

ASP.NET Core中DI容器的生命周期如下:

  • Transient:每次请求都创建一个新的服务实例。
  • Scoped:在同一作用域(例如同一HTTP请求)中,每次请求只创建一个服务实例。
  • Singleton:整个应用程序中只创建一个服务实例。

实现原理

ASP.NET Core中的DI容器基于
Microsoft.Extensions.DependencyInjection库实现。该库主要包含以下三个核心类:

  • ServiceCollection:服务集合,用于注册服务。
  • ServiceProvider:服务提供者,用于解析服务。
  • ServiceDescriptor:服务描述符,用于描述服务的类型、实现和生命周期。

在ASP.NET Core中,服务提供者(ServiceProvider)采用了服务提供者模式。服务提供者模式是指,在软件系统中,提供一种机制,能够让开发人员更加方便地获取系统所提供的各种服务。服务提供者模式的核心思想就是将服务的创建和使用分离开来,即服务的创建交给容器去处理,而服务的使用则由开发人员自行控制。

为了实现服务提供者模式,我们需要一个容器来管理服务。在ASP.NET Core中,容器主要用于注册服务、解析服务、生命周期管理等。

容器一般包含两个主要角色:服务描述符(ServiceDescriptor)和服务提供者(ServiceProvider)。服务描述符用于描述服务,例如服务接口类型、服务实现类型、生命周期等;而服务提供者则用于创建和管理服务实例。

ServiceCollection容器

在ASP.NET Core中,我们使用ServiceCollection容器来注册服务。ServiceCollection类继承于IServiceCollection接口,用于注册服务描述符并最终构建出ServiceProvider容器。ServiceCollection提供了一系列方便的方法来简化服务注册的过程。例如,通过调用AddTransient、AddScoped、AddSingleton等方法,我们可以轻松地注册服务。

ServiceCollection会在构建出ServiceProvider容器之前验证注册的服务描述符,以确保其合法性。例如,当注册多个同一服务类型的描述符时,ServiceCollection会抛出异常。另外,在
ServiceCollection.BuildServiceProvider() 方法中,容器将递归检查和解析所有服务描述符,构造出DI框架的核心实例(ServiceProvider)。

ServiceProvider容器

ServiceProvider是一个抽象类,表示服务提供者。在ASP.NET Core中,我们常用的是ServiceProvider的派生类:ServiceProviderEngine。ServiceProviderEngine是IServiceProvider接口的一个实现,它封装了所有服务实例的创建和管理过程,可以通过ServiceProviderFactory 派生类中的CreateServiceProvider来创建或指定它。

在ServiceProviderEngine中,每个服务都有一个对应的ServiceCallSite(调用站点),用于记录服务的描述信息。ServiceCallSite主要由以下三个部分组成:

  1. CallType,表示服务的运行时类型。
  2. ImplementationType,表示服务的实现类型。
  3. Cache,表示服务实例的缓存。

在获取服务实例时,ServiceProviderEngine先从缓存中查找服务实例,如果没有找到则根据 CallType 和 ImplementationType 创建新的服务实例。同时,也会处理服务的生命周期,根据服务描述符中的Lifetime设置,选择相应的范围进行限制。

集成Autofac等IOC框架

ASP.NET Core自带的依赖注入容器已经能够满足大多数场景需求,但是有时候需要在项目中使用其他的IOC框架,比如Autofac。下面将介绍如何在ASP.NET Core中集成Autofac,以实现更加便捷的依赖注入。

Autofac是一个用于依赖注入(Dependency Injection)的开源.NET容器。它提供了一种简单而灵活的方式来管理对象的创建和生命周期,使得应用程序的组件可以松耦合、可测试和可扩展。

以下是一些关于Autofac的链接:

  1. Autofac官方网站:https://autofac.org/
  2. Autofac在Github上的仓库:https://github.com/autofac/Autofac
  3. Autofac的文档:https://autofac.readthedocs.io/
  4. Autofac的NuGet包:https://www.nuget.org/packages/Autofac/

以下是一些使用Autofac的示例代码:

  1. 注册和解析一个简单的依赖关系:
// 创建容器构建器
var builder = new ContAInerBuilder();
// 注册依赖关系
builder.RegisterType<MyDependency>().As<IMyDependency>();
// 构建容器
var container = builder.Build();
// 解析依赖关系
var myDependency = container.Resolve<IMyDependency>();
  1. 使用构造函数注入:
public class MyClass
{
    private readonly IMyDependency _myDependency;
    public MyClass(IMyDependency myDependency)
    {
        _myDependency = myDependency;
    }
    // ...
}
// 注册依赖关系
builder.RegisterType<MyClass>();
// 解析依赖关系
var myClass = container.Resolve<MyClass>();
  1. 使用属性注入:
public class MyClass
{
    [Autowired]
    public IMyDependency MyDependency { get; set; }
    // ...
}

// 注册依赖关系
builder.RegisterType<MyClass>();
// 解析依赖关系
var myClass = container.Resolve<MyClass>();

这些示例只是Autofac的一小部分功能,更多详细的使用方法和示例可以在官方文档中找到。

 

 

安装Autofac

首先,在ASP.NET Core项目中安装Autofac和
Autofac.Extensions.DependencyInjection NuGet包。

可以通过NuGet包管理器或者通过命令行来安装:

  • NuGet包管理器:在Visual Studio中打开NuGet包管理器,搜索并安装Autofac和Autofac.Extensions.DependencyInjection包。
  • 命令行:在项目根目录下打开命令行工具,并执行以下两个命令:
dotnet add package Autofac
dotnet add package Autofac.Extensions.DependencyInjection

配置Autofac

在ASP.NET Core中,可以通过IServiceCollection接口来注册服务描述符,并最终构建出ServiceProvider容器。而Autofac也提供了相应的配置类来实现服务的注册和解析。

下面是一个简单的Autofac配置示例:

public class AutofacModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        // 注册服务
        builder.RegisterType<MyService>().As<IMyService>();

        // 将Autofac容器作为ServiceProvider容器
        builder.Populate(services);
    }
}

在上述代码中,我们创建了一个Autofac的Module类,并在其Load方法中进行服务注册。这里我们将MyService类注册为IMyService的实现类型,并将Autofac容器作为ServiceProvider容器。

注册Autofac容器

最后,我们需要在ASP.NET Core的ConfigureServices方法中注册Autofac容器:

public void ConfigureServices(IServiceCollection services)
{
    // 配置Autofac
    var builder = new ContainerBuilder();
    builder.RegisterModule(new AutofacModule());

    // 将Autofac容器设置为默认的依赖注入容器
    var container = builder.Build();
    return new AutofacServiceProvider(container);

    // 注册其他服务
    services.AddMvc();
}

在上述代码中,我们通过AutofacModule来配置Autofac,并创建了Autofac容器。最后,我们将Autofac容器设置为默认的依赖注入容器,即返回AutofacServiceProvider对象。这样就完成了Autofac与ASP.NET Core的集成。

总结

通过对ASP.NET Core DI容器的注册、解析和生命周期等方面进行深入探讨,我们能够更好地理解容器IOC和依赖注入的实现原理。同时,我们也能更好地使用ASP.NET Core的DI容器来进行应用程序开发,从而提高应用程序的性能和可维护性。

参考资料:
https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-7.0



Tags:.NET   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
.Net开发中十种常见的内存错误以及相应的解决方案
在.Net开发中,为内存管理方面提供了许多便利,但仍然存在一些常见的错误和陷阱。这些错误可能导致内存泄漏、性能下降、异常抛出等问题,严重影响应用程序的稳定性和性能。在软件...【详细内容】
2024-03-26  Search: .NET  点击:(12)  评论:(0)  加入收藏
.NET配置文件大揭秘:轻松读取JSON、XML、INI和环境变量
概述:.NET中的IConfiguration接口提供了一种多源读取配置信息的灵活机制,包括JSON、XML、INI文件和环境变量。通过示例,清晰演示了从这些不同源中读取配置的方法,使配置获取变得...【详细内容】
2023-12-28  Search: .NET  点击:(92)  评论:(0)  加入收藏
.Net开发都应当掌握的泛型基础知识集合
在C#编程语言中,泛型是一项非常强大和重要的功能。它允许我们编写更加灵活和通用的代码,同时提高代码的可重用性和性能。本文将介绍C#泛型的一些关键知识点,帮助读者理解和应用...【详细内容】
2023-12-25  Search: .NET  点击:(123)  评论:(0)  加入收藏
作为 .NET 开发人员,我为什么开始使用 Python?
作者 | Alex Maher编译 | 小欧作为一名 .NET 开发人员,很长一段时间以来,我一直关注 C# 和 .NET 的出色工具和功能。但我最近开始使用 Python,感觉非常棒。这里申明一点,这篇文...【详细内容】
2023-12-25  Search: .NET  点击:(142)  评论:(0)  加入收藏
.NET领域性能最好的对象映射框架Mapster使用方法
Mapster是一个开源的.NET对象映射库,它提供了一种简单而强大的方式来处理对象之间的映射。在本文中,我将详细介绍如何在.NET中使用Mapster,并提供一些实例和源代码。和其它框架...【详细内容】
2023-12-22  Search: .NET  点击:(77)  评论:(0)  加入收藏
.NET Core 3.1 升级到 .NET 8,看看都有哪些变化
.NET Core 3.1 已经用了很长一段时间,其实在 2022 年的年底微软已经不提供支持了,后面的一个 LTS 版本 .NET 6 也会在 2024 年 11 月终止支持,所以直接升级到 .NET 8 是最好的...【详细内容】
2023-12-08  Search: .NET  点击:(191)  评论:(0)  加入收藏
.NET Core的中间件来对Web API进行流量限制实现方法
在.NET Core中,我们可以使用ASP.NET Core的中间件来对Web API进行流量限制。ASP.NET Core提供了一个名为RateLimit的开源库,可以方便地实现流量限制功能。下面将详细介绍如何...【详细内容】
2023-12-06  Search: .NET  点击:(176)  评论:(0)  加入收藏
微软官方出品微服务架构:十个.Net开源项目
1、一个高性能类型安全的.NET枚举实用开源库Enums.NET是一个.NET枚举实用程序库,专注于为枚举提供丰富的操作方法。它支持.NET Framework和.Net Core。它主要优点表现在类型...【详细内容】
2023-12-06  Search: .NET  点击:(131)  评论:(0)  加入收藏
.NET开源的处理分布式事务的解决方案
前言在分布式系统中,由于各个系统服务之间的独立性和网络通信的不确定性,要确保跨系统的事务操作的最终一致性是一项重大的挑战。今天给大家推荐一个.NET开源的处理分布式事务...【详细内容】
2023-11-30  Search: .NET  点击:(173)  评论:(0)  加入收藏
深入 .NET 异步编程:Task 与 ValueTask 的区别与选择
在 .NET 中,Task 和 ValueTask 都是用于表示异步操作的类型,但它们有一些重要的区别。TaskTask 是最常见的表示异步操作的类型。它通常用于表示耗时的、异步的操作,比如从文件...【详细内容】
2023-11-26  Search: .NET  点击:(189)  评论:(0)  加入收藏
▌简易百科推荐
.Net开发中十种常见的内存错误以及相应的解决方案
在.Net开发中,为内存管理方面提供了许多便利,但仍然存在一些常见的错误和陷阱。这些错误可能导致内存泄漏、性能下降、异常抛出等问题,严重影响应用程序的稳定性和性能。在软件...【详细内容】
2024-03-26  小乖兽技术  今日头条  Tags:.Net   点击:(12)  评论:(0)  加入收藏
.NET配置文件大揭秘:轻松读取JSON、XML、INI和环境变量
概述:.NET中的IConfiguration接口提供了一种多源读取配置信息的灵活机制,包括JSON、XML、INI文件和环境变量。通过示例,清晰演示了从这些不同源中读取配置的方法,使配置获取变得...【详细内容】
2023-12-28  架构师老卢  今日头条  Tags:.NET   点击:(92)  评论:(0)  加入收藏
.Net开发都应当掌握的泛型基础知识集合
在C#编程语言中,泛型是一项非常强大和重要的功能。它允许我们编写更加灵活和通用的代码,同时提高代码的可重用性和性能。本文将介绍C#泛型的一些关键知识点,帮助读者理解和应用...【详细内容】
2023-12-25  小乖兽技术  今日头条  Tags:.Net   点击:(123)  评论:(0)  加入收藏
作为 .NET 开发人员,我为什么开始使用 Python?
作者 | Alex Maher编译 | 小欧作为一名 .NET 开发人员,很长一段时间以来,我一直关注 C# 和 .NET 的出色工具和功能。但我最近开始使用 Python,感觉非常棒。这里申明一点,这篇文...【详细内容】
2023-12-25    51CTO  Tags:.NET   点击:(142)  评论:(0)  加入收藏
.NET Core 3.1 升级到 .NET 8,看看都有哪些变化
.NET Core 3.1 已经用了很长一段时间,其实在 2022 年的年底微软已经不提供支持了,后面的一个 LTS 版本 .NET 6 也会在 2024 年 11 月终止支持,所以直接升级到 .NET 8 是最好的...【详细内容】
2023-12-08  不止dotNET  微信公众号  Tags:.NET   点击:(191)  评论:(0)  加入收藏
.NET Core的中间件来对Web API进行流量限制实现方法
在.NET Core中,我们可以使用ASP.NET Core的中间件来对Web API进行流量限制。ASP.NET Core提供了一个名为RateLimit的开源库,可以方便地实现流量限制功能。下面将详细介绍如何...【详细内容】
2023-12-06  架构师老卢  今日头条  Tags:.NET   点击:(176)  评论:(0)  加入收藏
微软官方出品微服务架构:十个.Net开源项目
1、一个高性能类型安全的.NET枚举实用开源库Enums.NET是一个.NET枚举实用程序库,专注于为枚举提供丰富的操作方法。它支持.NET Framework和.Net Core。它主要优点表现在类型...【详细内容】
2023-12-06  编程乐趣  今日头条  Tags:.Net   点击:(131)  评论:(0)  加入收藏
.NET开源的处理分布式事务的解决方案
前言在分布式系统中,由于各个系统服务之间的独立性和网络通信的不确定性,要确保跨系统的事务操作的最终一致性是一项重大的挑战。今天给大家推荐一个.NET开源的处理分布式事务...【详细内容】
2023-11-30  追逐时光者  微信公众号  Tags:.NET   点击:(173)  评论:(0)  加入收藏
深入 .NET 异步编程:Task 与 ValueTask 的区别与选择
在 .NET 中,Task 和 ValueTask 都是用于表示异步操作的类型,但它们有一些重要的区别。TaskTask 是最常见的表示异步操作的类型。它通常用于表示耗时的、异步的操作,比如从文件...【详细内容】
2023-11-26  架构师老卢  微信公众号  Tags: .NET   点击:(189)  评论:(0)  加入收藏
.NET字符串存储:解析常量与动态字符串,深入了解内存机制
在 .NET 中,字符串是不可变的,这意味着一旦创建,字符串的内容就不能被修改。字符串在内存中以不同的方式存储,具体取决于它是常量字符串还是动态创建的字符串。常量字符串常量字...【详细内容】
2023-11-25  架构师老卢  微信公众号  Tags:.NET   点击:(193)  评论:(0)  加入收藏
站内最新
站内热门
站内头条