.Net Core5.0中Autofac依赖注入整合多层,项目中可直接用 |
您所在的位置:网站首页 › userservice可以没有属性注入 › .Net Core5.0中Autofac依赖注入整合多层,项目中可直接用 |
一、配置Autofac替换内置DI
1.安装Nuget包:Autofac,Autofac.Extensions.DependencyInjection
2.Program.cs中CreateHostBuilder方法后加上.UseServiceProviderFactory(new AutofacServiceProviderFactory()) ; 告诉程序要使用Autofac。
3.Startup.cs中增加方法ConfigureContainer(ContainerBuilder containerBuilder),实例注入的地方,配置完成。 /// /// Autofac注册服务的地方,Autofac会自动调用 /// /// 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().As().InstancePerDependency();; 单例注入:containerBuilder.RegisterType().As().SingleInstance(); 生命周期注入: containerBuilder.RegisterType().As().InstancePerLifetimeScope(); /// /// Autofac注册服务的地方,Autofac会自动调用 /// /// public void ConfigureContainer(ContainerBuilder containerBuilder) { //注册服务 containerBuilder.RegisterType().As(); }访问/User/Index,_userService成功注入,正确获取结果。 三、属性注入 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 /// /// IPropertySelector:查看属性上是否标记某一个特性 /// 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());
5.把容器注册到IOC容器,在Startup.cs的ConfigureContainer()增加 //获取所有控制器类型并使用属性注入 Type[] controllersTypeAssembly = typeof(Startup).Assembly.GetExportedTypes() .Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray(); containerBuilder.RegisterTypes(controllersTypeAssembly).PropertiesAutowired(new AutowiredPropertySelector());
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().As();
运行程序,能看到增加了注入标识的userService注入成功,没加标识的orderService没有注入。 四、批量注入 实际项目中那么多需要注入的类,一个个写注册就不太现实了,需要一个可以批量注入的方法。 1.新建三个空接口IScopeDenpendency.cs,ISingletonDenpendency.cs,ITransitDenpendency.cs /// /// 瞬时注入 /// public interface ITransitDenpendency { } /// /// 单例注入标识 /// public interface ISingletonDenpendency { } /// /// 生命周期注入标识 /// public interface IScopeDenpendency { }2.把上面要注入的类实现上面的接口
3.新增一个IocManger类 /// /// 批量注入扩展 /// /// /// 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改成 /// /// Autofac注册服务的地方,Autofac会自动调用 /// /// 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的代码变成 /// /// Autofac注册服务的地方,Autofac会自动调用 /// /// public void ConfigureContainer(ContainerBuilder containerBuilder) { containerBuilder.RegisterModule(); }五、手动获取实例 手动获取实例的场景有静态帮助类中获取实例,例如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; } } } } /// /// 手动获取实例 /// /// /// public static T Resolve() { return _container.Resolve(); }2.在Startup.cs的Configure()中增加 //获取Autofac容器上下文信息IocManager.InitContainer(app.ApplicationServices.GetAutofacRoot());3.验证,新建一个DataHelper.cs类 public class DataHelper { //手动注入UserService private static IUserService userService = IocManager.Resolve(); public static string GetData() { return userService.GetUserName(); } }修改UserController用DataHelper的方法成功获取数据 六、其它用法 1.不用接口,直接注入实例 public class UserService :ITransitDenpendency { public string GetUserName() { return "张三"; } } 2.一接口多实现 public class UserService :IUserService { public string GetUserName() { return "张三"; } } public class User2Service : IUserService { public string GetUserName() { return "张三2号"; } }
最后:源码地址:https://github.com/weixiaolong325/.NetCore5.0AutofacDemo 演示项目结构:
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |