在 .net core 2.1 和 3.1 中使用 autofac

通过本文你可以获得如何用 autofac 替换 .NET CORE(2.1,3.1) 默认 IOC 容器。

生命周期说明

  • 每个依赖一个实例(Instance Per Dependency) (默认) ----InstancePerDependency()

  • 单一实例(Single Instance) 单例 ----SingleInstance()

  • 每个生命周期作用域一个实例(Instance Per Lifetime Scope)----InstancePerLifetimeScope()

  • 每个匹配的生命周期作用域一个实例(Instance Per Matching Lifetime Scope)----InstancePerMatchingLifetimeScope()

  • 每个请求一个实例(Instance Per Request) asp.net web请求----InstancePerRequest()

  • 每次被拥有一个实例(Instance Per Owned) ----InstancePerOwned()

注册方式

  • 反射

  • 使用实例

  • lambda 表达式

示例代码说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 创建注册组件的builder
var builder = new ContainerBuilder();

//根据类型注册组件 ConsoleLogger 暴漏服务:ILogger
builder.RegisterType<ConsoleLogger>().As<ILogger>();

//根据类型注册组件 ConsoleLogger,暴漏其实现的所有服务(接口)
builder.RegisterType<ConsoleLogger>().AsImplementedInterfaces();

// 根据实例注册组件 output 暴漏服务:TextWriter
var output = new StringWriter();
builder.RegisterInstance(output).As<TextWriter>();

//表达式注册组件,这里我们是在构造函数时传参->"musection" 暴漏服务:IConfigReader
builder.Register(c =new ConfigReader("mysection")).As<IConfigReader>();

//表达式注册组件,解析时传参
var service = scope.Resolve<IConfigReader>(
new NamedParameter("section", "mysection"));

//反射注册组件,直接注册了ConsoleLogger类(必须是具体的类),如果ConsoleLogger有多个构造函数,将会取参数最多的那个构造函数进行实例化
builder.RegisterType<ConsoleLogger>();

//反射注册组件,手动指定构造函数,这里指定了调用 MyComponent(ILogger log,IConfigReader config)的构造函数进行注册
builder.RegisterType<MyComponent>()
.UsingConstructor(typeof(ILogger), typeof(IConfigReader));

//注册MySingleton类中的静态变量"Instance",ExternallyOwned()函数指定自己控制实例的生命周期,而不是由autofac自动释放
builder.RegisterInstance(MySingleton.Instance).ExternallyOwned();

//一个组件暴漏两个服务
builder.RegisterType<CallLogger>().As<ILogger>().As<ICallInterceptor>();

//注册当前程序集中以“Service”结尾的类
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces();
//注册"MyApp.Repository"程序集中所有的类
builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();

//构建一个容器完成注册
var rootcontainer = builder.Build();

//可以通过下面这种方式手动获取IConfigReader 的实现类
//这种手动解析的方式需要 从生命周期作用域内获取组件,以保证组件最终被释放
//不要直接从根容器rootcontainer中解析组件,很有可能会导致内存泄漏
using(var scope = rootcontainer.BeginLifetimeScope())
{
var reader = scope.Resolve<IConfigReader>();
}

ASP.NET CORE 2.1 中的使用

.NET CORE 2.2 和 3.1 对 Autofac 的初始化方式不一样,需要注意下,建议使用 3.1。

需要安装一下的库:

  • Autofac@5.1.3

  • Autofac.Extensions.DependencyInjection@6.0.0

注册策略:Module

在不同层中定义一个 ModuleRegister 类,用于注册类型

  • 这里以 Application 层为例,多层的话可以分别进行定义

IocPolicy.cs

1
2
3
4
5
6
7
8
9
10
public class IocPolicy : Module
{
protected override void Load(ContainerBuilder builder)
{
//注册当前程序集中以“Ser”结尾的类,暴漏类实现的所有接口,生命周期为PerLifetimeScope
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().SingleInstance();
//注册所有"MyApp.Repository"程序集中的类
//builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
}
}

接管默认 IoC 引擎

需要修改 Startup.cs,需要调整 ConfigServices 方法签名,以让 autofac 接管 ioc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public static IContainer AutofacContainer;
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddControllers();

#region >>AutoFac 1/2
ContainerBuilder builder = new ContainerBuilder();
//将services中的服务填充到Autofac中.
builder.Populate(services);
//新模块组件注册
builder.RegisterModule<Application.IocPolicy>();
builder.RegisterModule<Domain.IocPolicy>();
//创建容器.
AutofacContainer = builder.Build();
//使用容器创建 AutofacServiceProvider
return new AutofacServiceProvider(AutofacContainer);
#endregion
}


public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime appLifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
#region >>AutoFac 2/2
//程序停止调用函数
appLifetime.ApplicationStopped.Register(() => { AutofacContainer.Dispose(); });
#endregion
}

ASP.NET CORE 3.1 中的使用

这里跟 core 2.2不一样,更加偏向于默认的 IoC 容器了,也方便了不少。

需要安装以下的库:

  • Autofac@5.1.3

  • Autofac.Extensions.DependencyInjection@6.0.0

类型注册

在不同层中定义一个 ModuleRegister 类,用于注册类型

  • 这里以 Application 层为例,多层的话可以分别进行定义

IocPolicy.cs

1
2
3
4
5
6
7
8
9
10
public static class IocPolicy
{
public static void RegisterApplication(this ContainerBuilder builder)
{
//注册当前程序集中以“Ser”结尾的类,暴漏类实现的所有接口,生命周期为PerLifetimeScope
builder.RegisterAssemblyTypes(System.Reflection.Assembly.GetExecutingAssembly()).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().SingleInstance();
//注册所有"MyApp.Repository"程序集中的类
//builder.RegisterAssemblyTypes(GetAssembly("MyApp.Repository")).AsImplementedInterfaces();
}
}

接管默认 IoC 引擎

需要修改 Startup.cs,需要调整 ConfigServices 方法签名,以让 autofac 接管 ioc

1
2
3
4
5
6
7
8
9
            /* 新增加如下方法,用于注册类型 */

public void ConfigureContainer(ContainerBuilder builder)
{
#region >>AutoFac
builder.RegisterApplication();
builder.RegisterDomain();
#endregion
}

Program.cs

1
2
3
4
5
6
7
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) //autofac 接管
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});