Autofac的使用
是IOC容器 支持三种类型DI 配置文件配置映射关系 支持AOP扩展
.Net Core中具体使用步骤
1.导入Nuget包
2. Progam中的CreateHostBuilder方法,使用autofac的容器工厂替换系统默认的容器
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())//使用autofac的容器工厂替换系统默认的容器
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
3. 在Startup中增加一个方法ConfigureContainer
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
//指定服务的注册
containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope().AsImplementedInterfaces();
containerBuilder.RegisterType<ProductService>().As<IProductService>().InstancePerLifetimeScope().AsImplementedInterfaces();
var container = containerBuilder.Build();
IUserService userService = container.Resolve<IUserService>();
IProductService productService = container.Resolve<IProductService>();
userService.Show();
productService.Show();
}
这样写 一看就可以发现 随着接口的增加 我们每次都需要手动在container方法中进行注册 很麻烦 这是我们就可以利用反射 如下
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
Assembly service = Assembly.Load("AspNetCore.Ioc.Service");
Assembly iservice = Assembly.Load("AspNetCore.Ioc.Interface");
containerBuilder.RegisterAssemblyTypes(service, iservice)
.Where(t => t.FullName.EndsWith("Service") && !t.IsAbstract) //类名以service结尾,且类型不能是抽象的
.InstancePerLifetimeScope() //生命周期,,
.AsImplementedInterfaces()
.PropertiesAutowired(); //属性注入
}
当遇到一个接口多个现实时 我们也可以指定注册 如下
//一个接口有多个实现:注册所有实现的服务实例
builder.RegisterAssemblyTypes(Assembly.Load("AspNetCore.Ioc.Service")).As<IUserService>();
//一个接口有多个实现:只注册以A结尾的服务实例
builder.RegisterAssemblyTypes(Assembly.Load("AspNetCore.Ioc.Service")).Where(c=>c.Name.EndsWith("A")).As<IUserService>();
//一个接口有多个实现:注册所有实现的服务实例,并排除UserServiceA服务实例
builder.RegisterAssemblyTypes(Assembly.Load("AspNetCore.Ioc.Service")).Except<UserServiceA>().As<IUserService>();
但是随之我们也发现 这样Startup中的代码还是会越来越多
这时我们可以采用自定义AutofacModule的方式进行简化 将服务注册的代码抽离出来 放置在单独的文件中
接下来我们新建一个类 MyAutofacModule类 用于服务注册的处理
using System.Linq;
using System.Reflection;
using Autofac;
using Autofac.Configuration;
using Microsoft.Extensions.Configuration;
namespace AspNetCore.Ioc.Web.Utility
{
public class MyAutofacModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
//反射程序集方式服务注册
Assembly service = Assembly.Load("AspNetCore.Ioc.Service");
Assembly iservice = Assembly.Load("AspNetCore.Ioc.Interface");
builder.RegisterAssemblyTypes(service, iservice)
.Where(t => t.FullName.EndsWith("Service") && !t.IsAbstract) //类名以service结尾,且类型不能是抽象的
.InstancePerLifetimeScope() //作用域生命周期
.AsImplementedInterfaces()
.PropertiesAutowired(); //属性注入
}
}
}
然后只需要将startup中的ConfigureContainer方法修改一下 如下
public void ConfigureContainer(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterModule<MyAutofacModule>();
}
就可以了
4. 除了新建注册类 我们还可以通过配置文件 进行注册优化 同时也使服务注册变得更加灵活
配置文件格式如下
{
"defaultAssembly": "AspNetCore.Ioc.Interface", //接口所在的程序集名称
"components": [
{
"type": "AspNetCore.Ioc.Service.UserService,AspNetCore.Ioc.Service", //接口的实现 全名称
"services": [
{
"type": "AspNetCore.Ioc.Interface.IUserService" // 接口的全名称
}
],
"instanceScope": "single-instance", //单例生命周期
"injectProperties": true //是否支持属性注入
},
{
"type": "AspNetCore.Ioc.Service.ProductService,AspNetCore.Ioc.Service", //接口的实现 全名称
"services": [
{
"type": "AspNetCore.Ioc.Interface.IProductService" // 接口的全名称
}
],
"instanceScope": "single-instance", //单例生命周期
"injectProperties": true //是否支持属性注入
}
]
}
【注】记得修改配置文件属性-->始终复制
接着再修改MyAutofacModule中的调用方法 如下
protected override void Load(ContainerBuilder builder)
{
//Autofac 基于配置文件的服务注册
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddJsonFile("Config/autofac.json");
IConfigurationRoot root = configurationBuilder.Build();
//开始读取配置文件中的内容
ConfigurationModule module = new ConfigurationModule(root);
//根据配置文件的内容注册服务
builder.RegisterModule(module);
}
这样就可以了