如何在ASP.NET 8.0+ 中使用依赖注入框架Autofac

前言

为什么需要Autofac

.NET 提供了其轻量级的内置框架Microsoft.Extention.DependencyInjection,用于实现依赖注入(DI)、控制反转(IoC)。但是这个框架的依赖注册(Register)比较繁琐,只能单个依赖地注入。Autofac是一个第三方的.NET Core 框架,该框架的一大优点就是可以结合反射,对一个程序集(Assembly)内的实现了接口的类进行分别的依赖注册(官网首页的Register Compenents部分有示例代码)。

为什么需要这篇文章

然而,国内社区中 .NET 相关的资料不太多,也比较落后。而且,Autofac 提供的中文文档的最新版本是4.0版本,落后于最新版本是7.0版本的英文文档。此外,英文文档似乎也没有更新,至少其中的集成应用中的ASP.NET Core 的介绍没有使用最新的语法。根据文档,我找到了Autofac 在Github 上的示例代码,结果我需要的部分都是3年前的版本。

这三年ASP.NET Core 做了许多的改变。C# 9.0(大约3年前)开始引入的顶级语句在后续的ASP.NET Core 中被应用,Startup.cs 文件不再需要,Program.cs 也有了很多的变化。3年前的实例代码中启动应用的方法,和现如今ASP.NET Core 提供的模板差别很大,无法用于学习。

入门

我认为官方文档中创建ContainerBuilder对象、然后用其进行注册的方法在现今版本的ASP.NET Core 中是不可行的,因为我能看到的实例代码中,这一步都是在Startup.cs文件中的某一个方法内。而且,ASP.NET Core 似乎做了很多的更改,导致网上的许多过时的指导中需要用的方法、对象都不可用。

我在StackOverFlow 上看到了一篇问答,最后找到了合适的使用方法。原文链接:stackoverflow.com/questions/6... 。根据这篇这篇问答以及我的亲身实验,我总结出了以下指南(只是介绍下流程,具体的流程下的原理之类的我也不清楚)

简述流程

C# 复制代码
using Autrofac;
using Autofac.Extentions.DependencyInjection;

var builder = new WebApplication(args);

// 重点
// 将Autofac 的依赖容器提供给WebApplication,
// 这样,通过Autofac 注册的组件就能够被注入
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());

var app = builder.Build();
app.Run();

组件注册(Registering Components)

和过时的官方文档一样,注册组件的方法也是要通过ContainerBuilder对象进行,但是我们不需要(或者说不能)去手动创建这个对象,而是交由AutofacServiceProviderFactory类。首先看一下这个类的一个构造函数

csharp 复制代码
/// <summary>
/// Initializes a new instance of the <see cref="AutofacServiceProviderFactory"/> class.
/// </summary>
/// <param name="configurationAction">Action on a <see cref="ContainerBuilder"/> that adds component registrations to the container..</param>
public AutofacServiceProviderFactory(Action<ContainerBuilder>? configurationAction = null)

可以看到,这个构造函数接受一个类型为Action<ContainerBuilder>的委托,注释指出该委托用于像Autofac 依赖容器中添加组件。也就是说,我们要把文档中使用ContainerBuilder对象进行组件注册的代码写在一个委托中,再将这个委托作为AutofacServiceProviderFactory的构造函数的参数传入。

这样也有好处,我会在Program.cs文件中定一个签名与委托匹配的方法,在其中进行必要的依赖注入,也有利于增强顶级语句的可读性。

需要注意的是,据我观察,同时使用Autofac 以及内置的依赖注入进行注册都是有效的。也就是说,以上相当于把通过Autofac 注入的组件并入内置依赖注入框架的容器中(不太严谨地说)。个人感觉像DbContext、控制器的注册,还是用内置依赖注入好。我使用Autfofac,主要也是为了补充内置框架的不足。

依赖注入

官方文档指出,可以使用隐式的依赖注入,我也有验证过,构造器注入的方式确实是隐式有效的。具体详见官方文档,目测没有太多改变。Resolving Services --- Autofac 7.0.0 documentation

我的示例

C# 复制代码
using System.Reflection;
using Autofac;
using Autofac.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

// controllers
builder.Services.AddControllers();

// Redis
builder.Services.AddSingleton<IDatabase>(_ => ConnectionMultiplexer
    .Connect(builder.Configuration.GetConnectionString("Redis") ?? throw new Exception("Connection string 'Redis' not found."))
    .GetDatabase()
);

// DbContext
builder.Services.AddDbContext<DiggingSoilContext>(options =>
    options.UseMySQL(builder.Configuration.GetConnectionString("MySql") ?? throw new Exception("Connection string 'MySql' not found."))
);

// Use Autofac
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory(DependencyHelper));
var app = builder.Build();
app.Run();

void AutofacContainerBuilderConfiguration(ContainerBuilder containerBuilder)
{
    // Services
    containerBuilder.RegisterAssemblyTypes(Assembly.Load("MyProject.Services"))
        .Where(t => t.IsClass && t.Name.EndsWith("Service"))
        .AsImplementedInterfaces()
        .SingleInstance();

    // Repos
    containerBuilder.RegisterAssemblyTypes(Assembly.Load("MyProject.Dal"))
        .Where(t => t.IsClass && t.Name.EndsWith("Repo"))
        .AsImplementedInterfaces()
        .SingleInstance();
}

如有错误,欢迎指正

相关推荐
friklogff10 分钟前
【C#生态园】虚拟现实与增强现实:C#开发库全面评估
c#·ar·vr
VB.Net13 分钟前
EmguCV学习笔记 VB.Net 12.1 二维码解析
opencv·计算机视觉·c#·图像·vb.net·二维码·emgucv
虚假程序设计6 小时前
pythonnet python图像 C# .NET图像 互转
开发语言·人工智能·python·opencv·c#·.net
我是苏苏7 小时前
Web开发:ABP框架3——入门级别的接口增删改查实现原理
c#·web开发·abp
Zhen (Evan) Wang7 小时前
.NET 6 API + Dapper + SQL Server 2014
数据库·c#·.net
VB.Net7 小时前
EmguCV学习笔记 VB.Net 12.3 OCR
opencv·计算机视觉·c#·ocr·图像·vb.net·emgucv
俊哥V7 小时前
[备忘]测算.net中对象所占用的内存
c#·.net·内存
闻缺陷则喜何志丹7 小时前
HObject复制耗时试用
c#·指针·halcon·key·图形图形·用时·非安全代码
friklogff8 小时前
【C#生态园】从数据分析到机器学习:掌握C#统计学库的核心功能
机器学习·数据分析·c#
我命由我123458 小时前
GPIO 理解(基本功能、模拟案例)
linux·运维·服务器·c语言·c++·嵌入式硬件·c#