.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

  • A+
所属分类:.NET技术
摘要

1.安装Nuget包:Autofac,Autofac.Extensions.DependencyInjection   2.Program.cs中CreateHostBuilder方法后加上.UseServiceProviderFactory(new AutofacServiceProviderFactory()) ; 告诉程序要使用Autofac。


一、配置Autofac替换内置DI

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

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

 

 

2.Program.cs中CreateHostBuilder方法后加上.UseServiceProviderFactory(new AutofacServiceProviderFactory()) ; 告诉程序要使用Autofac。

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

 

 3.Startup.cs中增加方法ConfigureContainer(ContainerBuilder containerBuilder),实例注入的地方,配置完成。

 /// <summary>         /// Autofac注册服务的地方,Autofac会自动调用         /// </summary>         /// <param name="containerBuilder"></param>         public void ConfigureContainer(ContainerBuilder containerBuilder)         {          }

二、构造函数注入

新建IUserService,类UserService,控制器UserController

 public interface IUserService     {         public string GetUserName();     }

 public class UserService     {         public string GetUserName()         {             return "张三";         }     }

 public class UserController : Controller     {         private readonly IUserService _userService;         public UserController(IUserService userService)         {             _userService = userService;         }         public IActionResult Index()         {             string name = _userService.GetUserName();             return Content(name);         }     }

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

瞬时注入:containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerDependency();;

单例注入:containerBuilder.RegisterType<UserService>().As<IUserService>().SingleInstance();

生命周期注入: containerBuilder.RegisterType<UserService>().As<IUserService>().InstancePerLifetimeScope();

 /// <summary>         /// Autofac注册服务的地方,Autofac会自动调用         /// </summary>         /// <param name="containerBuilder"></param>         public void ConfigureContainer(ContainerBuilder containerBuilder)         {             //注册服务             containerBuilder.RegisterType<UserService>().As<IUserService>();         }

访问/User/Index,_userService成功注入,正确获取结果。

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

三、属性注入

1.把UserController改成属性注入形式,属性注入有一个问题,就是那些属性需要注入?全部注入没必要,父类也有很多属性,要按需注入,给属性增加一个自定义特性标识说明需要注入。

 public class UserController : Controller     {         [AutowiredProperty]         private IUserService userService { get; set; }         public IActionResult Index()         {             string name = userService.GetUserName();             return Content(name);         }     }

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

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

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

 /// <summary>     /// IPropertySelector:查看属性上是否标记某一个特性     /// </summary>    public class AutowiredPropertySelector : IPropertySelector     {         public bool InjectProperty(PropertyInfo propertyInfo, object instance)         {             //判断属性的特性是否包含自定义的属性,标记有返回true             return propertyInfo.CustomAttributes.Any(s => s.AttributeType == typeof(AutowiredPropertyAttribute));         }     }

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

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

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

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

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

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

 6.验证结果,新增一个接口IOrderService.cs和一个实现类OrderService.cs做对比

 public interface IOrderService     {         public string CreateOrder();     }  public class OrderService : IOrderService     {         public string CreateOrder()         {             return "下单成功";         }     }

把UserController改成

  public class UserController : Controller     {         [AutowiredProperty]         private IUserService userService { get; set; }          private IOrderService orderService { get; set; }//不加属性注入标识         public IActionResult Index()         {             string name = userService.GetUserName();             return Content(name);         }     }

注入方法ConfigureContainer()增加

containerBuilder.RegisterType<OrderService>().As<IOrderService>();

 

运行程序,能看到增加了注入标识的userService注入成功,没加标识的orderService没有注入。

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

四、批量注入

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

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

  /// <summary>     /// 瞬时注入     /// </summary>     public interface ITransitDenpendency     {     }   /// <summary>     /// 单例注入标识     /// </summary>     public interface ISingletonDenpendency     {     }    /// <summary>     /// 生命周期注入标识     /// </summary>     public interface IScopeDenpendency     {     }

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

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

 

3.新增一个IocManger类

  /// <summary>         /// 批量注入扩展         /// </summary>         /// <param name="builder"></param>         /// <param name="assembly"></param>         public static void BatchAutowired(this ContainerBuilder builder, Assembly assembly)         {              var transientType = typeof(ITransitDenpendency); //瞬时注入             var singletonType = typeof(ISingletonDenpendency); //单例注入             var scopeType = typeof(IScopeDenpendency); //单例注入             //瞬时注入             builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(transientType))                 .AsSelf()                 .AsImplementedInterfaces()                 .InstancePerDependency()                 .PropertiesAutowired(new AutowiredPropertySelector());             //单例注入             builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(singletonType))                .AsSelf()                .AsImplementedInterfaces()                .SingleInstance()                .PropertiesAutowired(new AutowiredPropertySelector());             //生命周期注入             builder.RegisterAssemblyTypes(assembly).Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Contains(scopeType))                .AsSelf()                .AsImplementedInterfaces()                .InstancePerLifetimeScope()                .PropertiesAutowired(new AutowiredPropertySelector());          }

 

4.把注入类ConfigureContainer改成

 /// <summary>         /// Autofac注册服务的地方,Autofac会自动调用         /// </summary>         /// <param name="containerBuilder"></param>         public void ConfigureContainer(ContainerBuilder containerBuilder)         {             //获取所有控制器类型并使用属性注入            Type[] controllersTypeAssembly = typeof(Startup).Assembly.GetExportedTypes()                .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();             containerBuilder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());              //批量自动注入,把需要注入层的程序集传参数             containerBuilder.BatchAutowired(typeof(UserService).Assembly);             containerBuilder.BatchAutowired(typeof(UserRepository).Assembly);         }

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

 public class AutofacRegisterModule:Autofac.Module     {         protected override void Load(ContainerBuilder builder)         {             //获取所有控制器类型并使用属性注入             Type[] controllersTypeAssembly = typeof(Startup).Assembly.GetExportedTypes()                 .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();             builder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());              //批量自动注入,把需要注入层的程序集传参数             builder.BatchAutowired(typeof(UserService).Assembly);             builder.BatchAutowired(typeof(UserRepository).Assembly);         }     }

ConfigureContainer的代码变成

/// <summary>         /// Autofac注册服务的地方,Autofac会自动调用         /// </summary>         /// <param name="containerBuilder"></param>         public void ConfigureContainer(ContainerBuilder containerBuilder)         {             containerBuilder.RegisterModule<AutofacRegisterModule>();         }

 

五、手动获取实例

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

1.在上面的IocManager类中增加

 private static object obj = new object();  private static ILifetimeScope _container { get; set; }    public static void InitContainer(ILifetimeScope container)         {             //防止过程中方法被调用_container发生改变             if (_container == null)             {                 lock (obj)                 {                     if (_container == null)                     {                         _container = container;                     }                 }             }         }         /// <summary>         /// 手动获取实例         /// </summary>         /// <typeparam name="T"></typeparam>         /// <returns></returns>         public static T Resolve<T>()         {             return _container.Resolve<T>();         }

2.在Startup.cs的Configure()中增加

//获取Autofac容器上下文信息
IocManager.InitContainer(app.ApplicationServices.GetAutofacRoot());

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

 public class DataHelper     {         //手动注入UserService         private static IUserService userService = IocManager.Resolve<IUserService>();         public static string GetData()         {             return userService.GetUserName();         }     }

修改UserController用DataHelper的方法成功获取数据

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

六、其它用法

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

 public class UserService :ITransitDenpendency     {         public string GetUserName()         {             return "张三";         }     }

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

 2.一接口多实现

 public class UserService :IUserService     {         public string GetUserName()         {             return "张三";         }     }   public class User2Service : IUserService     {         public string GetUserName()         {             return "张三2号";         }     }

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用

 

 

 

最后:源码地址:https://github.com/weixiaolong325/.NetCore5.0AutofacDemo

演示项目结构:

.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用