当前位置:   article > 正文

.NET 7 中 Autofac 依赖注入整合多层,项目中可直接用

autofac 注入类

一、配置Autofac替换内置DI

1、安装Nuget包:Autofac.Extensions.DependencyInjection

62f2b39530dba7c4f1cb50471798c3ea.png

2、Program.cs中加上

  1. builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
  2. builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
  3. {
  4.     //在这里写注入代码
  5. });
6b14bbd6616b10c7048a86f6460ef929.png

二、构造函数注入

新建IUserService,类UserService

  1. public interface IUserService
  2. {
  3.     public string GetUserName();
  4. }
  5. public class UserService:IUserService
  6. {
  7.     public string GetUserName()
  8.     {
  9.         return "张三";
  10.     }
  11. }

在上面的ConfigureContainer方法把UserService注入进来,默认是瞬时注入

瞬时注入

containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerDependency();

单例注入

containerBuilder.RegisterType< UserService >().As< IUserService>().SingleInstance();

生命周期注入

containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();
ee841a1944abc8e13b0d5530e32e0d72.png

注入试下是否注入成功

46447bcb37e22a987e1a4703cc6fcb46.png

调用成功,证明注入成功

三、属性注入

1、把HomeController改成属性注入形式,属性注入有一个问题,就是那些属性需要注入?

全部注入没必要,父类也有很多属性,要按需注入,给属性增加一个自定义特性标识说明需要注入。

  1. public class HomeController : Controller
  2. {
  3.     [AutowiredProperty]
  4.     private IUserService userService { get; set; }
  5.     public IActionResult Index()
  6.     {
  7.         string name = userService.GetUserName();
  8.           return View();
  9.     }
  10. }

2、新增自定义特性类AutowiredPropertyAttribute.cs

  1. [AttributeUsage(AttributeTargets.Property)]
  2. //为了支持属性注入,只能打到属性上
  3. public class AutowiredPropertyAttribute: Attribute
  4. {
  5. }

3、增加识别特性类AutowiredPropertySelector.cs

  1. public class AutowiredPropertySelector : IPropertySelector
  2. {
  3.     public bool InjectProperty(PropertyInfo propertyInfo, object instance)
  4.     {
  5.         //判断属性的特性是否包含自定义的属性,标记有返回true
  6.         return propertyInfo.CustomAttributes.Any(s => s.AttributeType == typeof(AutowiredPropertyAttribute));
  7.     }
  8. }

4、因为Controller 默认是由 Mvc 模块管理的,需要把控制器放到IOC容器中,在Program.cs中增加

  1. //让控制器实例由容器创建
  2. builder.Services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

5、把容器注册到IOC容器,在Program.cs的ConfigureContainer()增加

  1. //获取所有控制器类型并使用属性注入
  2. Type[] controllersTypeAssembly = typeof(Program).Assembly.GetExportedTypes()
  3.     .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
  4. containerBuilder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());
a7a55f9adf27315eb502dc15dea41af6.png

验证:

66235a978dad0eabfd808e8e60eecbb4.png

成功。

四、批量注入

实际项目中那么多需要注入的类,一个个写注册就不太现实了,需要一个可以批量注入的方法。

1、新建三个空接口IScopeDenpendency.cs,ISingletonDenpendency.cs,ITransitDenpendency.cs

  1. /// <summary>
  2. /// 瞬时注入
  3. /// </summary>
  4. public interface ITransitDenpendency
  5. {
  6. }
  7. /// <summary>
  8. /// 单例注入标识
  9. /// </summary>
  10. public interface ISingletonDenpendency
  11. {
  12. }
  13. /// <summary>
  14. /// 生命周期注入标识
  15. /// </summary>
  16. public interface IScopeDenpendency
  17. {
  18. }

2、把上面要注入的类实现上面的接口

2d72420b58fd3de2af2dc6a59edb96b1.png

3、新增一个IocManager类

  1. /// <summary>
  2. /// Ioc管理
  3. /// </summary>
  4. public static class IocManager
  5. {
  6.      /// <summary>
  7.      /// 批量注入扩展
  8.      /// </summary>
  9.      /// <param name="builder"></param>
  10.      /// <param name="assembly"></param>
  11.      public static void BatchAutowired(this ContainerBuilder builder, Assembly assembly)
  12.      {
  13.          var transientType = typeof(ITransitDenpendency); //瞬时注入
  14.          var singletonType = typeof(ISingletonDenpendency); //单例注入
  15.          var scopeType = typeof(IScopeDenpendency); //单例注入
  16.          //瞬时注入
  17.          builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(transientType))
  18.              .AsSelf()
  19.              .AsImplementedInterfaces()
  20.              .InstancePerDependency()
  21.              .PropertiesAutowired(new AutowiredPropertySelector());
  22.          //单例注入
  23.          builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(singletonType))
  24.             .AsSelf()
  25.             .AsImplementedInterfaces()
  26.             .SingleInstance()
  27.             .PropertiesAutowired(new AutowiredPropertySelector());
  28.          //生命周期注入
  29.          builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(scopeType))
  30.             .AsSelf()
  31.             .AsImplementedInterfaces()
  32.             .InstancePerLifetimeScope()
  33.             .PropertiesAutowired(new AutowiredPropertySelector());
  34.      }
  35. }

4、把注入类ConfigureContainer改成

769d2ec0c0041284fa01938e7bc5bbc8.png

5、防止Program.cs代码过多,建一个Module把注入代码搬走,新建AutofacRegisterModule.cs类把ConfigureContainer的代码移过去

  1. public class AutofacRegisterModule : Autofac.Module
  2. {
  3.     protected override void Load(ContainerBuilder builder)
  4.     {
  5.         //获取所有控制器类型并使用属性注入
  6.         Type[] controllersTypeAssembly = typeof(Program).Assembly.GetExportedTypes()
  7.             .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();
  8.         builder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());
  9.         //批量自动注入,把需要注入层的程序集传参数,注入Service层的类
  10.         builder.BatchAutowired(typeof(UserService).Assembly);
  11.         //注入其它层的containerBuilder.BatchAutowired(typeof(其它层的任务一个类).Assembly);
  12.     }
  13. }

ConfigureContainer的代码变成

ea60ebd8e930a740c853376f8e0d5829.png

五、手动获取实例

手动获取实例的场景有静态帮助类中获取实例,例如redisHelper中获取注入的配置文件中的连接字符串

1、在上面的IocManager类中增加

  1. private static object obj = new object();
  2. private static ILifetimeScope _container { get; set; }
  3. public static void InitContainer(ILifetimeScope container)
  4. {
  5.     //防止过程中方法被调用_container发生改变
  6.     if (_container == null)
  7.     {
  8.         lock (obj)
  9.         {
  10.             if (_container == null)
  11.             {
  12.                 _container = container;
  13.             }
  14.         }
  15.     }
  16. }
  17. /// <summary>
  18. /// 手动获取实例
  19. /// </summary>
  20. /// <typeparam name="T"></typeparam>
  21. /// <returns></returns>
  22. public static T Resolve<T>()
  23. {
  24.     return _container.Resolve<T>();
  25. }

2、在Program.cs中增加

e1a1bef26e282a106ce24425e9ed32fd.png

3、验证,新建一个DataHelper.cs类

  1. public class DataHelper
  2. {
  3.     //手动注入UserService
  4.     private static IUserService userService = IocManager.Resolve<IUserService>();
  5.     public static string GetData()
  6.     {
  7.         return userService.GetUserName();
  8.     }
  9. }
1672864d0c62252d796f6c047750c029.png

成功获取到值,证明从容器中获取成功。

六、其它用法

1、不用接口,直接注入实例

  1. public class UserService :ITransitDenpendency  
  2.    public string GetUserName()  
  3.    { 
  4.      return "张三";  
  5.    }  
  6. }
5352f1deedd2cf04f3bc17c04d7ba09b.png

2、一接口多实现

  1. public class UserService :IUserService
  2. {
  3.     public string GetUserName()
  4.     {
  5.         return "张三";
  6.     }
  7. }
  8. public class UserService2 : IUserService
  9. {
  10.     public string GetUserName()
  11.     {
  12.         return "张三2号";
  13.     }
  14. }
a02209308fd6b75838bfeb1733a42b19.png

转自:包子wxl

链接:cnblogs.com/wei325/p/17481596.html

- EOF -

技术群:添加小编微信dotnet999

公众号:dotnet讲堂

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

闽ICP备14008679号