当前位置:   article > 正文

Autofac详解_autofacserviceproviderfactory

autofacserviceproviderfactory

Autofac详解

零、文章目录

一、Autofac详解

1、概述

2、快速开始

(1)Nuget引入程序包

Autofac   基于版本6.3演示,Net5

(2)容器创建对象

  1. //创建一个容器建造者
  2. ContainerBuilder containerBuilder = new ContainerBuilder();
  3. //注册普通类
  4. containerBuilder.RegisterType<Honer>();
  5. //build一下,得到一个容器
  6. IContainer container = containerBuilder.Build();
  7. //可以基于容器来获取对象的实例
  8. Honer phone = container.Resolve<Honer>();

3、注册的类型

(1)注册普通类

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>();
  3. IContainer container = containerBuilder.Build();
  4. Honer phone = container.Resolve<Honer>();

(2)注册抽象与实现

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>();
  3. IContainer container = containerBuilder.Build();
  4. IPhone phone = container.Resolve<IPhone>();

(3)注册程序集

  • RegisterAssemblyTypes(程序集数组),程序集必须是public的
  • AsImplementedInterfaces():表示注册的类型,以接口的方式注册
  • PropertiesAutowired():支持属性注入
  • Where:满足条件类型注册

  1. var basePath = AppContext.BaseDirectory;
  2. var dll = Path.Combine(basePath, "MyAutofac.dll");
  3. ContainerBuilder containerBuilder = new ContainerBuilder();
  4. var assemblysServices = Assembly.LoadFrom(dll);
  5. containerBuilder.RegisterAssemblyTypes(assemblysServices)
  6. .Where(t => !t.Name.EndsWith("XXX"))
  7. .AsImplementedInterfaces()
  8. .PropertiesAutowired();
  9. IContainer container = containerBuilder.Build();
  10. ITeacher teacher = container.Resolve<ITeacher>();

image-20220615171348335

4、三种注入方式

(1)构造函数注入

默认支持,无法用特性进行筛选,默认选参数最多的构造函数进行注入

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>();
  3. containerBuilder.RegisterType<Teacher>().As<ITeacher>();
  4. containerBuilder.RegisterType<Student>().As<IStudent>();
  5. IContainer container = containerBuilder.Build();
  6. ITeacher teacher = container.Resolve<ITeacher>();

image-20220507144924795

(2)全部属性注入

关键词PropertiesAutowired,这个对象所有属性全部注入

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>();
  3. containerBuilder.RegisterType<Teacher>().As<ITeacher>().PropertiesAutowired();
  4. containerBuilder.RegisterType<Student>().As<IStudent>();
  5. IContainer container = containerBuilder.Build();
  6. ITeacher teacher = container.Resolve<ITeacher>();

image-20220507145543126

(3)标记特性的属性注入

关键词PropertiesAutowired,定义特性选择器CustomPropertySelector

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>();
  3. containerBuilder.RegisterType<Teacher>().As<ITeacher>().PropertiesAutowired(new CustomPropertySelector());
  4. containerBuilder.RegisterType<Student>().As<IStudent>();
  5. IContainer container = containerBuilder.Build();
  6. ITeacher teacher = container.Resolve<ITeacher>();

  1. public class CustomPropertySelector : IPropertySelector
  2. {
  3. public bool InjectProperty(PropertyInfo propertyInfo, object instance)
  4. {
  5. var flag = propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(SelectPropAttribute));
  6. return flag;
  7. }
  8. }

image-20220507151030788

(4)方法注入

关键词OnActivated,指定调用方法

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>();
  3. containerBuilder.RegisterType<Teacher>().As<ITeacher>()
  4. .OnActivated(p =>
  5. {
  6. p.Instance.SetStudent1(p.Context.Resolve<IStudent>());
  7. });
  8. containerBuilder.RegisterType<Student>().As<IStudent>();
  9. IContainer container = containerBuilder.Build();
  10. ITeacher teacher = container.Resolve<ITeacher>();

image-20220507154431887

5、对象生命周期

(1)瞬时生命周期

每次获取都是全新的实例,关键词InstancePerDependency,默认的生命周期

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerDependency();
  3. IContainer container = containerBuilder.Build();
  4. IPhone phone1 = container.Resolve<IPhone>();
  5. IPhone phone2 = container.Resolve<IPhone>();
  6. bool isflg1 = object.ReferenceEquals(phone1, phone2);
  7. Console.WriteLine($"InstancePerDependency:phone1==phone2=>{isflg1}");

InstancePerDependency:phone1==phone2=>False

(2)单例生命周期

同一个进程内都是同一个实例,关键词SingleInstance

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>().SingleInstance();
  3. IContainer container = containerBuilder.Build();
  4. IPhone phone1 = container.Resolve<IPhone>();
  5. IPhone phone2 = container.Resolve<IPhone>();
  6. bool isflg1 = object.ReferenceEquals(phone1, phone2);
  7. Console.WriteLine($"SingleInstance:phone1==phone2=>{isflg1}");
  8. using (var scope = container.BeginLifetimeScope())
  9. {
  10. IPhone phone3 = scope.Resolve<IPhone>();
  11. IPhone phone4 = scope.Resolve<IPhone>();
  12. bool isflg2 = object.ReferenceEquals(phone3, phone4);
  13. Console.WriteLine($"SingleInstance:phone3==phone4=>{isflg2}");
  14. bool isflg3 = object.ReferenceEquals(phone1, phone3);
  15. Console.WriteLine($"SingleInstance:phone1==phone3=>{isflg3}");
  16. }

  1. SingleInstance:phone1==phone2=>True
  2. SingleInstance:phone3==phone4=>True
  3. SingleInstance:phone1==phone3=>True

(3)作用域生命周期

同一个作用域内都是同一个实例,关键词InstancePerLifetimeScope

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerLifetimeScope();
  3. IContainer container = containerBuilder.Build();
  4. IPhone phone1 = container.Resolve<IPhone>();
  5. IPhone phone2 = container.Resolve<IPhone>();
  6. bool isflg1 = object.ReferenceEquals(phone1, phone2);
  7. Console.WriteLine($"InstancePerLifetimeScope:phone1==phone2=>{isflg1}");
  8. IPhone phone3 = null;
  9. IPhone phone4 = null;
  10. using (var scope = container.BeginLifetimeScope())
  11. {
  12. phone3 = scope.Resolve<IPhone>();
  13. phone4 = scope.Resolve<IPhone>();
  14. bool isflg2 = object.ReferenceEquals(phone3, phone4);
  15. Console.WriteLine($"InstancePerLifetimeScope:phone3==phone4=>{isflg2}");
  16. bool isflg3 = object.ReferenceEquals(phone1, phone3);
  17. Console.WriteLine($"InstancePerLifetimeScope:phone1==phone3=>{isflg3}");
  18. }
  19. IPhone phone5 = null;
  20. IPhone phone6 = null;
  21. using (var scope = container.BeginLifetimeScope())
  22. {
  23. phone5 = scope.Resolve<IPhone>();
  24. phone6 = scope.Resolve<IPhone>();
  25. bool isflg2 = object.ReferenceEquals(phone5, phone6);
  26. Console.WriteLine($"InstancePerLifetimeScope:phone5==phone6=>{isflg2}");
  27. bool isflg3 = object.ReferenceEquals(phone1, phone5);
  28. Console.WriteLine($"InstancePerLifetimeScope:phone1==phone5=>{isflg3}");
  29. }
  30. bool isflg4 = object.ReferenceEquals(phone3, phone5);
  31. Console.WriteLine($"InstancePerLifetimeScope:phone3==phone5=>{isflg4}");

  1. InstancePerLifetimeScope:phone1==phone2=>True
  2. InstancePerLifetimeScope:phone3==phone4=>True
  3. InstancePerLifetimeScope:phone1==phone3=>False
  4. InstancePerLifetimeScope:phone5==phone6=>True
  5. InstancePerLifetimeScope:phone1==phone5=>False
  6. InstancePerLifetimeScope:phone3==phone5=>False

(4)作用域范围生命周期

在作用域范围外无法创建实例,在作用域范围里面,同一个作用域下面的对象是同一个,关键词InstancePerMatchingLifetimeScope

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerMatchingLifetimeScope("scope1", "scope2");
  3. IContainer container = containerBuilder.Build();
  4. IPhone phone1 = null;
  5. IPhone phone2 = null;
  6. using (var scope = container.BeginLifetimeScope("scope1"))
  7. {
  8. phone1 = scope.Resolve<IPhone>();
  9. phone2 = scope.Resolve<IPhone>();
  10. bool isflg1 = object.ReferenceEquals(phone1, phone2);
  11. Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone2=>{isflg1}");
  12. }
  13. IPhone phone3 = null;
  14. using (var scope = container.BeginLifetimeScope("scope2"))
  15. {
  16. phone3 = scope.Resolve<IPhone>();
  17. }
  18. IPhone phone4 = null;
  19. using (var scope = container.BeginLifetimeScope("scope2"))
  20. {
  21. phone4 = scope.Resolve<IPhone>();
  22. }
  23. bool isflg2 = object.ReferenceEquals(phone3, phone4);
  24. Console.WriteLine($"InstancePerMatchingLifetimeScope:phone3==phone4=>{isflg2}");
  25. bool isflg3 = object.ReferenceEquals(phone1, phone3);
  26. Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone3=>{isflg3}");

  1. InstancePerMatchingLifetimeScope:phone1==phone2=>True
  2. InstancePerMatchingLifetimeScope:phone3==phone4=>False
  3. InstancePerMatchingLifetimeScope:phone1==phone3=>False

(5)一次请求同一个对象

关键词InstancePerRequest,只能在web项目中调试,控制台报错

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerRequest();
  3. IContainer container = containerBuilder.Build();
  4. IPhone phone1 = container.Resolve<IPhone>();
  5. IPhone phone2 = container.Resolve<IPhone>();
  6. bool isflg1 = object.ReferenceEquals(phone1, phone2);
  7. Console.WriteLine($"InstancePerRequest:phone1==phone2=>{isflg1}");

6、支持配置文件注册

(1)nuget引入程序集

  1. Autofac
  2. Autofac.Configuration
  3. Microsoft.Extensions.Configuration.Json

(2)配置文件autofac.json,属性->始终复制

  1. {
  2. "components": [
  3. {
  4. //实现
  5. "type": "Net5.IOC.Honer,Net5.IOC",
  6. //抽象
  7. "services": [
  8. {
  9. "type": "Net5.IOC.IPhone,Net5.IOC"
  10. }
  11. ],
  12. //生命周期
  13. "instanceScope": "single-instance",
  14. //属性注入
  15. "injectProperties": true
  16. }
  17. ]
  18. }

(3)通过配置文件注册创建对象

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. IConfigurationBuilder config = new ConfigurationBuilder();
  3. IConfigurationSource autofacJsonConfigSource = new JsonConfigurationSource()
  4. {
  5. Path = "Autofac/autofac.json",
  6. Optional = false,//boolean,默认就是false,可不写
  7. ReloadOnChange = true,//同上
  8. };
  9. config.Add(autofacJsonConfigSource);
  10. ConfigurationModule module = new ConfigurationModule(config.Build());
  11. containerBuilder.RegisterModule(module);
  12. IContainer container = containerBuilder.Build();
  13. IPhone phone1 = container.Resolve<IPhone>();
  14. IPhone phone2 = container.Resolve<IPhone>();
  15. bool isflg1 = object.ReferenceEquals(phone1, phone2);
  16. Console.WriteLine($"配置文件注册:phone1==phone2=>{isflg1}");

(4)运行结果

配置文件注册:phone1==phone2=>True

7、支持AOP切面编程

可以在不修改方法的前提下,在方法前后添加公共逻辑,日志,异常,缓存等

(1)nuget引入程序集

  1. Castle.Core
  2. Autofac.Extras.DynamicProxy

(2)自定义一个切面类实现IInterceptor接口

  1. public class CustomInterceptor : IInterceptor
  2. {
  3. public void Intercept(IInvocation invocation)
  4. {
  5. Console.WriteLine("方法执行前。。。");
  6. //执行当前方法
  7. invocation.Proceed();
  8. Console.WriteLine("方法执行后。。。");
  9. }
  10. }

(3)在抽象/实现类上添加特性标记

  1. [Intercept(typeof(CustomInterceptor))]
  2. public interface IPhone
  3. {
  4. string ShowName();
  5. }
  6. //实现类虚方法
  7. public class Honer : IPhone
  8. {
  9. public virtual string ShowName()
  10. {
  11. Console.WriteLine("Honer");
  12. return "Honer";
  13. }
  14. }

(4)在容器中注册关系创建对象

  • EnableInterfaceInterceptors + 特性标记在抽象上,所有实现类都支持AOP
  • EnableInterfaceInterceptors + 特性标记到实现类上,标记的类就支持AOP
  • EnableClassInterceptors,要支持AOP的方法必须要是用virtual虚方法
  • EnableClassInterceptors + 特性标记在抽象上,所有实现类都支持AOP
  • EnableClassInterceptors + 特性标记到实现类上,标记的类就支持AOP

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().As<IPhone>().EnableInterfaceInterceptors();
  3. containerBuilder.RegisterType(typeof(CustomInterceptor));
  4. IContainer container = containerBuilder.Build();
  5. IPhone phone = container.Resolve<IPhone>();
  6. phone.ShowName();

(5)运行结果

  1. 方法执行前。。。
  2. Honer
  3. 方法执行后。。。

8、单抽象多实现问题

(1)在容器中注册关系创建对象

注册的时候不标记名字,后注册的会覆盖先注册的
注册的时候标记下名字,创建对象的时候用名称来区分

  1. ContainerBuilder containerBuilder = new ContainerBuilder();
  2. containerBuilder.RegisterType<Honer>().Named<IPhone>("Honer");
  3. containerBuilder.RegisterType<Huawei>().Named<IPhone>("Huawei");
  4. IContainer container = containerBuilder.Build();
  5. IPhone honer = container.ResolveNamed<IPhone>("Honer");
  6. IPhone huawei = container.ResolveNamed<IPhone>("Huawei");
  7. honer.ShowName();
  8. huawei.ShowName();

(2)运行结果

  1. Honer
  2. Huawei

9、集成到Asp.NetCore5框架

(1)nuget引入程序集

  1. Autofac
  2. Autofac.Extensions.DependencyInjection

(2)定义实现类和抽象

  1. public class UserService : IUserService
  2. {
  3. private IUserRepository UserRepositoryCtor { get; set; }
  4. public UserService(IUserRepository userRepository)
  5. {
  6. UserRepositoryCtor = userRepository;
  7. }
  8. public string Login(string username, string password)
  9. {
  10. return "登录成功";
  11. }
  12. }

(3)添加控制器和页面

  1. public class FourthController : Controller
  2. {
  3. private IUserService _userService;
  4. public FourthController(IUserService userService)
  5. {
  6. this._userService = userService;
  7. }
  8. public IActionResult Index()
  9. {
  10. object result = this._userService.Login("username", "password");
  11. return View(result);
  12. }
  13. }

  1. @model String
  2. <h2>this is fourth index...</h2>
  3. <h2>@Model</h2>

(4)在Program替换容器工厂

  1. public class Program
  2. {
  3. public static void Main(string[] args)
  4. {
  5. CreateHostBuilder(args).Build().Run();
  6. }
  7. public static IHostBuilder CreateHostBuilder(string[] args) =>
  8. Host.CreateDefaultBuilder(args)
  9. .ConfigureWebHostDefaults(webBuilder =>
  10. {
  11. webBuilder.UseStartup<Startup>();
  12. })
  13. .UseServiceProviderFactory(new AutofacServiceProviderFactory());
  14. }

(5)在Startup类的ConfigureServices方法中替换创建控制器的类

  1. //控制器默认是有IControllerActivator创建的,替换成由容器创建
  2. services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

(6)注册抽象和实现的关系

Startup类中专门增加一个方法ConfigureContainer,用于注册抽象和实现,可以把这些注册信息进行模块化封装到AutofacModule

当抽象类和实现非常多的时候,可以将整个dll注册,特殊的关系可以写在后面覆盖前面的注册关系。

  1. /// <summary>
  2. /// Autofac专用:注册抽象和细节之间的关系,使用autofac后原来内置注册的关系要注释掉
  3. /// Autofac和ServiceCollection是二者并存的,Autofac会接管ServiceCollection的一切
  4. /// </summary>
  5. /// <param name="builder"></param>
  6. public void ConfigureContainer(ContainerBuilder builder)
  7. {
  8. builder.RegisterModule<AutofacModule>();
  9. }

  1. public class AutofacModule : Module
  2. {
  3. /// <summary>
  4. /// 重写Autofac管道中的Load方法,在这里注入注册的内容
  5. /// </summary>
  6. /// <param name="builder"></param>
  7. protected override void Load(ContainerBuilder builder)
  8. {
  9. //注册抽象与实现
  10. builder.RegisterType<UserRepository>().As<IUserRepository>();
  11. builder.RegisterType<UserService>().As<IUserService>();
  12. //注册所有控制器类
  13. var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes()
  14. .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
  15. //实现属性注入,这边无法实现方法注入
  16. builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();
  17. }
  18. }

(7)运行结果

image-20220617130527205

image-20220509140121017

(8)在StartupConfigure方法中用容器创建对象

  1. using (var container = host.Services.CreateScope())
  2. {
  3. IUserService userService = container.ServiceProvider.GetService<IUserService>();
  4. }

image-20220617131016831

(9)单抽象多实现集成到框架

注入的时候通过构造函数或者属性注入autofac上下文实例,再根据名称创建对应实例。

定义单抽象和多实例类

  1. //抽象
  2. public interface ITestService
  3. {
  4. string Show();
  5. }
  6. //实现1
  7. public class TestServiceA : ITestService
  8. {
  9. public string Show()
  10. {
  11. return "TestServiceA";
  12. }
  13. }
  14. //实现2
  15. public class TestServiceB : ITestService
  16. {
  17. public string Show()
  18. {
  19. return "TestServiceB";
  20. }
  21. }

AutofacModule注册抽象和实现的关系

  1. //单抽象多实现注册
  2. builder.RegisterType<TestServiceA>().Named<ITestService>("a");
  3. builder.RegisterType<TestServiceB>().Named<ITestService>("b");

添加控制器和页面

  1. public class FifthController : Controller
  2. {
  3. private IComponentContext _componentContext;
  4. public FifthController(IComponentContext componentContext)
  5. {
  6. this._componentContext = componentContext;
  7. }
  8. public IActionResult Index()
  9. {
  10. ITestService testServiceA = _componentContext.ResolveNamed<ITestService>("a");
  11. ITestService testServiceB = _componentContext.ResolveNamed<ITestService>("b");
  12. object result = $"{testServiceA.Show()}--{testServiceB.Show()}";
  13. return View(result);
  14. }
  15. }

  1. @model String
  2. <h2>this is Fifth index...</h2>
  3. <h2>@Model</h2>

运行结果

image-20220510102820041


---------------------
作者:李宥小哥
来源:CSDN
原文:https://blog.csdn.net/liyou123456789/article/details/125331813
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/141322
推荐阅读
相关标签
  

闽ICP备14008679号