autofac基础知识
前言:使用Autofac这一款IOC容器来替代Asp.Net Core自带的容器。
1. Autofac基础使用
准备工作:
编写一个抽象接口和一个具体实现类分别为:
public interface ITestServiceA { void Show(); } public class TestServiceA : ITestServiceA { public TestServiceA() { Console.WriteLine($"{this.GetType().Name} was Constructed"); } public void Show() { Console.WriteLine("AAA"); } }
(1) 管理NuGet程序包,下载安装【Autofac】。
(2) 在Startup.cs中的ConfigureServices注册服务。
- 创建 ContainerBuilder.
- 注册组件.
- 创建容器,将其保存以备后续使用.
- 应用执行阶段...
- 从容器中创建一个生命周期.
- 在此生命周期作用域内解析组件实例.
//创建ContainerBuilder ContainerBuilder containerBuilder = new ContainerBuilder(); //注册组件告诉容器哪些 组件 暴露了哪些 服务 //RegisterType注册的组件必须是个具体的类型 组件可以暴露抽象类和接口作为 服务 containerBuilder.RegisterType<TestServiceA>().As<ITestServiceA>(); //创建容器 IContainer container = containerBuilder.Build(); //从容器中获取一个生命周期 using (var scope = container.BeginLifetimeScope()) { //解析组件实例 var service = scope.Resolve<ITestServiceA>(); //调用服务 service.Show(); }
2. Autofac注入方式:
- 构造函数注入(默认支持构造函数注入)
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>(); var container = builder.Build(); using var scope = container.BeginLifetimeScope(); var testServiceA = scope.Resolve<ITestServiceA>(); testServiceA.Show();
在控制器中注入:
public HomeController(ITestServiceA serviceA, ILogger<HomeController> logger) { _serviceA = serviceA; _logger = logger; }
需要注意的点是当我们的某一个服务在内部引用了其他的服务的情况下,我们需要也注册该服务引用的服务。
如我在之前的准备工作中新增两个服务ITestServiceB,ITestServiceC。而服务C需要服务B的注入。
public interface ITestServiceB { void Show(); } public interface ITestServiceC { void Show(); } public class TestServiceB : ITestServiceB { public TestServiceB() { Console.WriteLine($"{this.GetType().Name} was Constructed"); } public void Show() { Console.WriteLine("BBB"); } } public class TestServiceC : ITestServiceC { public TestServiceC(ITestServiceB iTestServiceB) { Console.WriteLine($"{this.GetType().Name} was Constructed"); } public void Show() { Console.WriteLine("CCC"); } }
这个时候我们想要使用解析ITestServiceC,则在注册服务时,需要注册ITestServiceB。否则将会出现异常。
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceB>().As<ITestServiceB>(); builder.RegisterType<TestServiceC>().As<ITestServiceC>(); var container = builder.Build(); using var scope = container.BeginLifetimeScope(); var testServiceC = scope.Resolve<ITestServiceC>(); testServiceC.Show();
- 属性注入
新增一个服务ITestServiceD。其中有三个公共属性需要注入。
public class TestServiceD : ITestServiceD { public ITestServiceA TestServiceA { get; set; } public ITestServiceB TestServiceB { get; set; } public ITestServiceC TestServiceC { get; set; } public TestServiceD() { Console.WriteLine($"{this.GetType().Name} was Constructed"); } public void Show() { TestServiceC.Show(); Console.WriteLine("DDD"); } }
注入方式为调用.PropertiesAutowired()方法即可。
var builder = new ContainerBuilder(); builder.RegisterType<TestServiceA>().As<ITestServiceA>(); builder.RegisterType<TestServiceB>().As<ITestServiceB>(); builder.RegisterType<TestServiceC>().As<ITestServiceC>(); builder.RegisterType<TestServiceD>().As<ITestServiceD>().PropertiesAutowired(); var container = builder.Build(); using var scope = container.BeginLifetimeScope(); var testServiceD = scope.Resolve<ITestServiceD>(); testServiceD.Show();
- 方法注入
对ITestServiceB进行修改,增加一个方法注入ITestServiceA.
public class TestServiceB : ITestServiceB { public ITestServiceA TestServiceA { get; set; } public void SetService(ITestServiceA serviceA) { TestServiceA = serviceA; } public TestServiceB() { Console.WriteLine($"{this.GetType().Name} was Constructed"); } public void Show() { TestServiceA.Show(); Console.WriteLine("BBB"); } }
想要调用一个方法来设置组件上的某个值, 最简单的方法是使用 lambda表达式组件 然后在activator中进行正确的方法调用:
ContainerBuilder containerBuilder = new ContainerBuilder(); containerBuilder.RegisterType<TestServiceA>().As<ITestServiceA>(); containerBuilder.Register(c => { //创建变量来返回注册结果 var result = new TestServiceB(); //获取方法注入需要的服务 var dep = c.Resolve<ITestServiceA>(); //调用方法注入 result.SetService(dep); return result; }); IContainer container = containerBuilder.Build();
ITestServiceB serviceB = container.Resolve<TestServiceB>(); serviceB.Show();