因为 .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单元
});
复制代码
评论