Autofac 使用

蘆薈柚子茶發表於2022-01-01

Autofac 使用

本文第一節從基本的概念說起;

第二節以文字的方式,列出 Autofac 的使用步驟;

第三節,結合實際的程式碼,展示如何對 Autofac 進行配置;

第四節(未實現),將展示如何使用 Autofac 注入的服務;

第五節開始,將常用的注入方式、生命週期等記錄下來,以便翻查;

最後將會有一節其他內容,比如:描述 Autofac 如何支援 AOP。

1 基本概念

1.1 相關名詞

依賴倒置(DIP)

控制反轉(IoC:Inversion of control)

注入(DI:Dependency injection)

1.2 個人理解

DIP 依賴倒置原則:程式要依賴於抽象,不要依賴於細節(具體實現)。其中抽象一般指介面(Interface),細節指類(Class)。

IoC 一般翻譯為控制反轉,主要是為了降低模組與模組之間程式碼的耦合度,是一種理念,一種設計原則。

DI 是 IoC 的一種實現方式,為依賴注入的方式。具體做法就是通過一個統一的容器(DI 容器),來管理物件的建立和生存週期。

2 使用步驟

2.1 基本使用

  1. 引入 Autofac
  2. 在程式入口處:建立容器(Create a ContainerBuilder),註冊服務/元件(Register Components),構建並儲存容器(Build and store)
  3. 在程式執行過程中:從容器中建立擁有生命週期的例項(lifetime scope)

對應3.2基本使用

2.2 在ASP.NET Core 中使用(.NET6)

替換工廠方式:

  1. 引入 Autofac.Extensions.DependencyInjection
  2. 在程式入口處,替換 ServiceProviderFactory
  3. 呼叫 ConfigureContainer 方法,註冊自定義 Autofac 的 Module

對應3.3.NET6使用

3 實際配置

本節會提供多種配置方式,如基本配置方式(可應用於一般程式),.NET6配置方式(Web程式),配置檔案等方式,選擇其中一種配置方式即可。

3.1 引入

方式一:介面 NuGet 包新增

方式二:控制檯引入 NuGet 包

Install-package Autofac -Version 6.3.0

方式三:修改工程檔案

<PackageReference Include="Autofac" Version="6.3.0" />

3.2 基本使用

//1、建立容器 Create a ContainerBuilder
ContainerBuilder containerBuilder = new ContainerBuilder();
//2、註冊服務(官方稱 Component)
containerBuilder.RegisterType<TestService>().As<ITestService>();
//3、構建容器,建立例項;需要把 container 儲存起來以便後續使用
IContainer container = containerBuilder.Build();
//4、使用 container 建立例項
var service = container.Resolve<ITestService>();

3.3 .NET6中使用

1)引入 Autofac.Extensions.DependencyInjection

2)程式碼

//在 var app = builder.Build(); 前加入使用 Autofac 相關程式碼
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
    builder.RegisterModule<AutofacModule>();
});

其中,AutofacModule 為自定義的 Autofac 配置類,實現如下:

public class AutofacModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        //把服務的注入規則寫在這裡
        builder.RegisterType<TestService>().As<ITestService>();
    }
}

注:

工廠模式下,Autofac 在自己註冊服務之前,會先把 ServiceCollection 中註冊的服務全部接管過來,所以通過 .NET6 預設的 DI 容器方式注入的服務,也生效。

3.4 其他配置方式

3.4.1 配置檔案方式

1)引入程式集:Autofac.Configuration

2)配置檔案:

{
  "defaultAssembly": "TestMiniAPI",
  "components": [
    {
      "type": "TestMiniAPI.Services.TestService, TestMiniAPI",
      "services": [
        {
          "type": "TestMiniAPI.Services.ITestService, TestMiniAPI"
        }
      ],
      "instanceScope": "single-instance",
      "injectProperties": true
    }
  ]
}

3)配置程式碼

ContainerBuilder containerBuilder = new ContainerBuilder();
IConfigurationBuilder config = new ConfigurationBuilder();
IConfigurationSource autofacJsonConfigSource = new JsonConfigurationSource()
{
    Path = "ConfigFile/autofac.json",
    Optional = false, //預設是false
    ReloadOnChange = true, //預設是true
};
config.Add(autofacJsonConfigSource);
ConfigurationModule module = new ConfigurationModule(config.Build());
containerBuilder.RegisterModule(module);

5 註冊元件

官方文件:https://autofac.readthedocs.io/en/latest/register/registration.html

5.1 多種注入方式

//註冊具體的類
containerBuilder.RegisterType<TestService>();
containerBuilder.RegisterType(typeof(TestService));
//註冊例項
var testService = new TestService();
containerBuilder.RegisterInstance(testService).As<ITestService>();
//註冊建立例項的表示式
containerBuilder.Register(c => new TestService("Parameters")).As<ITestService>();
//註冊公開介面
containerBuilder.RegisterType<TestService>().As<ITestService>();
//屬性注入
containerBuilder.RegisterType<TestService>().As<ITestService>().PropertiesAutowired();
//方法注入
containerBuilder.RegisterType<TestService>().OnActivated(e => e.Instance.SetService(e.Context.Resolve<ITestChildService>())).As<ITestService>();

5.2 將所有註冊的服務都暴漏

//使用 AsSelf();
containerBuilder.RegisterType<TestService>().AsSelf().As<ITestService>();
//這樣下面兩句都可以執行
container.Resolve<TestService>();
container.Resolve<ITestService>();

5.3 多例注入

//Program.cs 注入
containerBuilder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(t => t.IsAssignableTo<ITestService>()));

//構造 TestService
container.Resolve<TestService>();
//建構函式時獲取所有注入例項 IEnumerable<ITestService> 
public TestController(IEnumerable<ITestService> testServices){}

5.4 程式集批量注入

Assembly assembly = Assembly.Load("AssemblyName");
//Assembly assembly = Assembly.GetExecutingAssembly();
containerBuilder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces().InstancePerDependency();

5.5 MVC控制器支援注入(屬性等注入)

控制器的例項是 IConrtollerActivator 來建立的,與一般的類不同,需要特殊處理。

6 生命週期

6.1 生命週期範圍

using(var scope = container.BeginLifetimeScope()){}
using(var scope = container.BeginLifetimeScope("ScopeName")){}

6.2 多種生命週期

//瞬態,對應 DI 容器的 Transient
InstancePerDependency();
//單例,對應 DI 容器的 Singleton
SingleInstance();
//每個生命週期範圍一個例項
InstancePerLifetimeScope();
//每個匹配生命週期範圍一個例項
InstancePerMatchingLifetimeScope("ScopeName");
//Web請求範圍一個例項
InstancePerRequest();
//
InstancePerOwned<MessageHandler>();

9 其他

9.1 Autofac 支援 AOP

1)引入程式集

Castle.Core(獨立在另外一個工程)

Autofac.Extras.DynamicProxy

2)切面類實現

實現 IInterceptor 介面

public class AutofacAOP : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("執行前");
        invocation.Proceed();
        Console.WriteLine("執行後");
    }
}

3)注入

containerBuilder.RegisterType<AutofacAOP>();
containerBuilder.RegisterType<Test>().As<ITest>().EnableInterfaceInterceptors();

4)標記介面

[Intercept(typeof(AutofacAOP))]
public interface ITest {}

參考來源

官網:https://autofac.org

官方示例程式碼:https://github.com/autofac/Examples

部分內容來自於朝夕教育的視訊

相關文章