本人闲聊-AutoFac
一,AutoFac的优点以及相关名词
优点
- 它是C#语言联系很紧密,也就是说C#里的很多编程方式都可以为Autofac使用,例如可以用Lambda表达式注册组件
- 较低的学习曲线,学习它非常的简单,只要你理解了IoC和DI的概念以及在何时需要使用它们
- XML配置支持
- 自动装配
- 与Asp.Net MVC 3集成
- 微软的Orchad开源程序使用的就是Autofac,从该源码可以看出它的方便和强大
- 速度快,轻量级性能高
相关名词
- 依赖倒置(DIP)程序要依赖于抽象,不要依赖于细节(具体实现)。其中抽象一般指接口(Interface),细节指类(Class)。
- 控制反转(IoC:Inversion of control)一种理念,设计原则,主要是为了降低模块与模块之间代码的耦合度
- 注入(DI:Dependency injection)IoC 的一种实现方式,为依赖注入的方式,通过一个统一的容器(DI 容器),来管理对象的创建和生命周期。
二,配置NuGet包
- Autofac
- Autofac.Configuration
- Autofac.Mvc5
可能存在版本冲突,自己根据提示随机应变一下
也可以直接使用使用下面这个包
- Autofac.Extensions.DependencyInjection
三,外援提示
https://www.cnblogs.com/chiyueqi/category/874830.html
https://www.cnblogs.com/mantgh/p/5122284.html
https://www.cnblogs.com/liupeng/p/4806184.html
https://www.cnblogs.com/masonblog/p/9584517.html
AutoFac官方文档: Getting Started — Autofac 6.0.0 documentation
四,代码实现
配置方式
方式一
//1、创建容器 Create a ContainerBuilder
ContainerBuilder containerBuilder = new ContainerBuilder();
//2、注册服务(官方称 Component)
containerBuilder.RegisterType<TestService>().As<ITestService>();
//3、构建容器,创建实例;需要把 container 存储起来以便后续使用
IContainer container = containerBuilder.Build();
//4、使用 container 创建实例
var service = container.Resolve<ITestService>();
方式二
//在 var app = builder.Build(); 前加入使用 Autofac 相关代码
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterModule<AutoFacModelRegister>();
});
AutoFacModelRegister.cs
public class AutoFacModelRegister : Module
{
protected override void Load(ContainerBuilder builder)
{
//把服务的注入规则写在这里
builder.RegisterType<TestService>().As<ITestService>();
}
}
基础使用
官方文档:https://autofac.readthedocs.io/en/latest/register/registration.html
一,构造函数注入
//在 Program.cs 中注入服务
containerBuilder.RegisterType<TestService>().As<ITestService>();
//注册具体的类
containerBuilder.RegisterType<TestService>();
containerBuilder.RegisterType(typeof(TestService));
//注册实例
var testService = new TestService();
containerBuilder.RegisterInstance(testService).As<ITestService>();
//注册创建实例的表达式
containerBuilder.Register(c => new TestService("Parameters")).As<ITestService>();
//注册公开接口
containerBuilder.RegisterType<TestService>().As<ITestService>();
//属性注入
containerBuilder.RegisterType<TestService>().As<ITestService>().PropertiesAutowired();
//方法注入
containerBuilder.RegisterType<TestService>().OnActivated(e => e.Instance.SetService(e.Context.Resolve<ITestChildService>())).As<ITestService>();
//构造函数注入
public class TestController
{
private readonly ITestService _testService;
public TestController(ITestService testService)
{
_testService = testService;
}
}
二,程序集批量注入
方式一
public class AutoFacModelRegister:Module
{
//重写管道load方法,进行注册注入
protected override void Load(ContainerBuilder builder)
{
//程序集注入业务服务(通过反射的方法动态获取程序集,"Repository","service"都需要注册)
//Load:加载程序集(自己项目的程序集名称)
Assembly? assembly = Assembly.Load("AssemblyName");
//var AppServices = Assembly.Load("Service");
//根据名称约定(服务层的接口和实现均以Repository结尾),实现服务接口和服务实现的依赖
builder.RegisterAssemblyTypes(assembly)
//(带有指定后缀的文件)
.Where(t => t.Name.EndsWith("Repository"))
//开放接口,注入
.AsImplementedInterfaces().InstancePerDependency();
}
}
方式二
public class AutoFacModelRegister:Module
{
//重写管道load方法,进行注册注入
protected override void Load(ContainerBuilder builder)
{
// 获取所有创建的项目Lib
var libs = DependencyContext.Default.CompileLibraries
.Where(x => !x.Serviceable && x.Type == "project").ToList();
// 将lib转成Assembly
List<Assembly> assemblies = new();
foreach (var lib in libs)
{
assemblies.Add(AssemblyLoadContext.Default
.LoadFromAssemblyName(new AssemblyName(lib.Name)));
}
// 反射获取其中所有的被接口修饰的类型,并区分生命周期
builder.RegisterAssemblyTypes(assemblies.ToArray())
.Where(t => t.IsAssignableTo<IocTagScope>() && !t.IsAbstract)
.AsSelf()
.AsImplementedInterfaces()
.InstancePerLifetimeScope()
.PropertiesAutowired();
builder.RegisterAssemblyTypes(assemblies.ToArray())
.Where(t => t.IsAssignableTo<IocTagSington>() && !t.IsAbstract)
.AsSelf()
.AsImplementedInterfaces()
.SingleInstance()
.PropertiesAutowired();
builder.RegisterAssemblyTypes(assemblies.ToArray())
.Where(t => t.IsAssignableTo<IocTagTransient>() && !t.IsAbstract)
.AsSelf()
.AsImplementedInterfaces()
.PropertiesAutowired();
builder.RegisterAssemblyTypes(assemblies.ToArray())
.Where(t => t.IsAssignableTo<ControllerBase>() && !t.IsAbstract)
.AsSelf()
.PropertiesAutowired();
}
}