写点什么

.NET6 引入 Autofac

  • 2021 年 11 月 18 日
  • 本文字数:2672 字

    阅读完需:约 9 分钟

因为 .NET6 自带的 IOC 容器不支持 属性注入 方法注入 也不支持 Config.json 配置文件

所以正式项目开发中 一般引入第三方开源的 Autofac 容器


1.Nuget 引入 Autofac 程序集

Autofac

Autofac.Extensions.DependencyInjection


2.Program.cs 类中 注册 Autofac

在 Program.cs 类 var app = builder.Build(); 前面 添加这一段 代码


builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());


引入 AutofacServiceProvider 工厂



3.添加 Autofac 注册函数

方法一 用代码注册服务

理论上 Autofac 可以直接 接管 NET6 自带的 IOC 容器 的所有注册 所以如前面已经写了

用 .Net6 IOC 注册的服务 这里就可以不用添加,但即然使用了 Autofac 还是建议将服务注册 写在 Autofac 专用的函数中

在引入 Autofac 代码下方直接 添加如下代码:


//Autofac 专用函数注册IHostBuilder hostBuilder = builder.Host.ConfigureContainer<ContainerBuilder>(builder =>{
//这里注册关系 builder.RegisterType<AccountDBContext>().As<DbContext>(); builder.RegisterType<VirtualWalletServiceApp>().As<IVirtualWalletService>();});
复制代码


这里注册规则是

builder.RegisterType<实现类>().As<接口类>().生命周期; 默认为瞬时生命周期


//                   实现类                  接口类        作用域生命周期  builder.RegisterType<AccountDBContext>().As<DbContext>().InstancePerLifetimeScope();//                                                       单例生命周期builder.RegisterType<AccountDBContext>().As<DbContext>().SingleInstance();//                                                       瞬时生命周期(不写默认就是瞬时)builder.RegisterType<AccountDBContext>().As<DbContext>().InstancePerDependency();
复制代码

方法二 配置文件中注册服务

如果服务经常变动 一套代码 部署不同的项目 服务切来切去比较频繁 最好是在配置文件中配置


第一步 Nuget 引入 Autofac.Configuration 包


第二步 在项目中添加 CfgFile.json 文件夹

文件夹下创建一个 Autofac.json 文件

注册服务的信息以 json 的格式写在配置文件中 内容如下:

{  "components": [    //规则如下
//{ // "type": "具体实现类的完整类名(命名空间.类名),具体实现类程序集名", // "services": [ // { // "type": "接口的完整类名(命名空间.类名),接口所在的程序集" // } // ], //"instanceScope": "single-instance", //生命周期 //"injectProperties": true // 是否要支持属性注入 //},
{ "type": "Business.ServiceForDDD.VirtualWalletServiceApp,Business.ServiceForDDD", //具体实现类的完整类名,程序集名 "services": [ { "type": "Business.Interface.IVirtualWalletService,Business.Interface" //接口的完整类名,程序集名 } ], "instanceScope": "Instance-PerLifetimeScope", ////(生命周期 Instance-PerLifetimeScope 作用域 Instance-PerDependency 瞬时 single-instance 单例) "injectProperties": false // 开启属性注入 }, { "type": "VirtualWalletRepository.Entity.AccountDBContext,VirtualWalletRepository", //具体实现类的完整类名,程序集名 "services": [ { "type": "Microsoft.EntityFrameworkCore.DbContext,Microsoft.EntityFrameworkCore" //接口的完整类名,程序集名 } ], "instanceScope": "Instance-PerDependency", //(生命周期 Instance-PerLifetimeScope 作用域 Instance-PerDependency 瞬时 single-instance 单例) "injectProperties": false // 开启属性注入 }
]}
复制代码


第三步

Autofac 专用注册函数中改成如果代码表示 读取配置文件来找 注册的关系

   IHostBuilder hostBuilder = builder.Host.ConfigureContainer<ContainerBuilder>(builder =>    {        IConfigurationBuilder config = new ConfigurationBuilder();        IConfigurationSource autofacJsonConfigSource = new JsonConfigurationSource()        {            Path = "CfgFile/Autofac.json",            Optional = false,//boolean,默认就是false,可不写            ReloadOnChange = true,//同上        };        config.Add(autofacJsonConfigSource);        ConfigurationModule module = new ConfigurationModule(config.Build());        builder.RegisterModule(module);    });
复制代码


4.Autofac 单抽象多实现的方法-1 直接引用具体

1.同一个接口 注册了多个实现类 后注入的类会覆盖 最后实例化的是最后个的注册的实现类

2.一个抽象多个实例,都注册了,可以通过一个 IEnumerable<抽象>,当做构造函数参数,可以获取到所有注册的具体的实例

3.注册一个抽象的多个实例资源,如下方式注册,可以在控制器的构造函数中,使用具体实现类型作为参数类型,可以匹配到不同到具体类型实例

       //一次性注册继承该IVirtualWalletService接口的所有的类        builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(t =>       	t.IsAssignableTo<IVirtualWalletService>()));
复制代码

4.构造函数注入的时候直接注入具体的类


    public VirtualWalletService _WalletService { get; }
public VirtualWalletController(VirtualWalletService WalletService) { this._WalletService = WalletService; }
复制代码


5.Autofac 创建 Module 类 分组注册

有些相同功能的类注册 想放到一起可以单独创建一个 Module 类 都在类里注册好

再 Program.cs 类中一次性注册整个 Module 组

新建一个类 继承 Autofac.Module

 public class AutofacModule : Autofac.Module    {        //注册分类        protected override void Load(ContainerBuilder builder)        {            //所有继承ITestServiceA的都注册了            builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource(t => t.IsAssignableTo<ITestServiceA>()));        }    }
复制代码


在 Program.cs 中 Autofac 专用注册函数里直接注册整组

   IHostBuilder hostBuilder = builder.Host.ConfigureContainer<ContainerBuilder>(builder =>    {			builder.RegisterModule<AutofacModule>(); //注册整 个Module单元   });
复制代码


用户头像

8年.net 老程序猿 后端工程狮 2021.01.30 加入

06年毕业,8年开发 4年架构。现在在公司打杂 有硬核文章,还有幽默风趣的诗和远方。

评论

发布
暂无评论
.NET6 引入Autofac