Bootstrap

.NET6 引入Autofac

因为 .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(builder =>
{

    //这里注册关系
    builder.RegisterType().As();
    builder.RegisterType().As();
});

这里注册规则是

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

//                   实现类                  接口类        作用域生命周期  
builder.RegisterType().As().InstancePerLifetimeScope();
//                                                       单例生命周期
builder.RegisterType().As().SingleInstance();
//                                                       瞬时生命周期(不写默认就是瞬时)
builder.RegisterType().As().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(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()));

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()));
        }
    }

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

   IHostBuilder hostBuilder = builder.Host.ConfigureContainer(builder =>
    {
			builder.RegisterModule(); //注册整 个Module单元
   });