前言

源自于晓晨在成都.net社区群的一篇文章 《晓晨的ASP.NET Core 奇淫技巧之伪属性注入》

他的思路是 Ioc容器替换 ControllerActivator,因为只能在控制器内完成属性注入,意识心痒痒,就开笔写了这样一篇

先分析一下属性注入的思路

属性注入的核心就是通过动态代理完成注入,在这个过程中,对源实例的属性/字段注入实体

想了一下,最近几天沉迷学习,没有写点什么技术分享了,又想起之前学习AspectCore的过程,就打算基于AspectCore制作属性注入


设计思路如下

可以看见无论是默认的特性注入AOP流程,还是我们自定义的代理工厂类,核心都是通过拦截执行过程到自定义的过滤器

个人选择实现的方式是自定义工厂类,也可以根据代码,实现特性注入的方式注入属性

到属性注入这一步,就是查找自定义的特性,有注入的特性的,则完成字段/属性注入


实例实现

属性注入的特性

  1. [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
  2. public class PropertyInjectAttribute: Attribute
  3. {
  4.  
  5. }

这个特性,我们约束了只能打在字段/属性上面

自定义过滤器/过滤器工厂类

过滤器

  1. internal class PropertyInjectInterceptor : IInterceptor
  2. {
  3. public bool AllowMultiple => true;
  4.  
  5. public bool Inherited { get ; set; }
  6. public int Order { get; set; }
  7.  
  8. public Task Invoke(AspectContext context, AspectDelegate next)
  9. {
  10. var instace = context.Implementation;
  11. var instanceType = instace.GetType();
  12.  
  13. var serviceProvider = context.ServiceProvider;
  14.  
  15. var bindingFlag = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
  16.  
  17. foreach (var field in instanceType
  18. .GetFields(bindingFlag)
  19. .Where(_field =>
  20. _field.GetCustomAttributes(typeof(PropertyInjectAttribute), true) != null &&
  21. _field.GetCustomAttributes(typeof(PropertyInjectAttribute), true).Length > &&
  22. _field.FieldType.IsInterface
  23. )
  24. )
  25. {
  26. var value = field.GetReflector().GetValue(instace);
  27.  
  28. if (value == null)
  29. {
  30. var service = serviceProvider.GetRequiredService(field.FieldType);
  31.  
  32. field.GetReflector().SetValue(instace, service);
  33. }
  34. }
  35.  
  36. foreach (var property in instanceType
  37. .GetProperties(bindingFlag)
  38. .Where(_property =>
  39. _property.GetCustomAttributes(typeof(PropertyInjectAttribute), true) != null &&
  40. _property.GetCustomAttributes(typeof(PropertyInjectAttribute), true).Length > &&
  41. _property.PropertyType.IsInterface
  42. )
  43. )
  44. {
  45. var value = property.GetReflector().GetValue(instace);
  46.  
  47. if (value == null)
  48. {
  49. var service = serviceProvider.GetRequiredService(property.PropertyType);
  50.  
  51. property.GetReflector().SetValue(instace, service);
  52. }
  53. }
  54.  
  55. return next(context);
  56. }
  57. }

过滤器工厂类

  1. public class PropertyInjectInterceptorFactory : InterceptorFactory
  2. {
  3. public override IInterceptor CreateInstance(IServiceProvider serviceProvider)
  4. {
  5. return serviceProvider.GetRequiredService<PropertyInjectInterceptor>();
  6. }
  7. }

启用过滤器工厂类

  1. services.AddScoped<PropertyInjectInterceptor>();
  2. services.ConfigureDynamicProxy(config =>
  3. {
  4. config.Interceptors.Add(new PropertyInjectInterceptorFactory());
  5. });
  6.  
  7. return services.BuildDynamicProxyProvider();

编写测试例子

  1. public interface IInterface
  2. {
  3. void Hello();
  4. }
  5.  
  6. internal class InterfaceService : IInterface
  7. {
  8. [PropertyInject]
  9. private IPropertyServer propertyServer;
  10.  
  11. [PropertyInject]
  12. private IPropertyServer _propertyServer { get; set; }
  13.  
  14. public void Hello()
  15. {
  16. Console.WriteLine("Hello");
  17. }
  18. }
  19.  
  20. [NonAspect]
  21. public interface IPropertyServer
  22. {
  23.  
  24. }
  25.  
  26. internal class PropertyServer: IPropertyServer
  27. {
  28.  
  29. }

属性注入的实现,我不想再被AOP代理一次,就打上了NopAspect特性,如果不介意的话,也可以不打


后话

我隐隐约约记得AspectCore是自带了属性注入的,奈何最近几天没写C#代码了,有点想念,就自己撸上,重复造轮子了

分享嘛,思路最重要,使用而言,有成熟的轮子肯定不要自己造,学习的话,就要有勇于造轮子的心思

打个小广告

如果有技术交流可以加NCC的群 24791014、436035237,我在群里,有任何关于asp.net core方面的问题或者建议都可以与我交流,非常欢迎

附上晓晨的链接

《ASP.NET Core 奇淫技巧之伪属性注入》

https://www.cnblogs.com/stulzq/p/12610026.html

基于AspectCore打造属性注入的更多相关文章

  1. 基于autofac的属性注入

    基于autofac的属性注入 什么是属性注入 在了解属性注入之前,要先了解一下DI(Dependency Injection),即依赖注入.在ASP.NET Core里自带了一个IOC容器,而且程序支 ...

  2. Java框架spring 学习笔记(六):属性注入

    属性注入:创建对象的时候,向类里面的属性设置值. Java属性注入有三种方法: 使用set方法注入 有参数构造注入 使用接口注入 Spring框架里面的属性注入方式 有参数构造属性注入 set方法属性 ...

  3. spring的基于XML方式的属性注入

    1.掌握spring的属性注入的方法: 1.1构造方法注入普通值---------<constructor-arg>标签的使用 首先新建一个类 package spring.day1.de ...

  4. Spring:特殊数据类型的属性注入(基于配置文件)

    该处提到的特殊数据类型指的是除了基础数据类型和String以外的其他常用的数据类型,如:List.Map.Set.以及pojo对象等.则我们创建的Person类定义为: package bjtu.we ...

  5. 详解 Spring 3.0 基于 Annotation 的依赖注入实现(转)

    使用 @Repository.@Service.@Controller 和 @Component 将类标识为 Bean Spring 自 2.0 版本开始,陆续引入了一些注解用于简化 Spring 的 ...

  6. 详解 Spring 3.0 基于 Annotation 的依赖注入实现--转载

    使用 @Repository.@Service.@Controller 和 @Component 将类标识为 Bean Spring 自 2.0 版本开始,陆续引入了一些注解用于简化 Spring 的 ...

  7. spring3——IOC之基于XML的依赖注入(DI )

    我们知道spring容器的作用是负责对象的创建和对象间关系的维护,在上一篇博客中我们讲到spring容器会先调用对象的无参构造方法创建一个空值对象,那么接下来容器就会对对象的属性进行初始化,这个初始化 ...

  8. SSM-Spring-07:Spring基于注解的di注入

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 注解: 说起注解,哇哦,每个人都或多或少的用到过 像什么@Overried,@Test,@Param等等之前就 ...

  9. 基于配置文件的Spring注入

    基于配置文件的Spring注入 1.依赖注入的概述 依赖注入指的是通过Spring配置文件的方式创建对象时,直接通过配置的方式将数据注入到该对象的标量类型属性,并从Spring容器中获取指定对象注入到 ...

随机推荐

  1. Oracle 对表的基本CURD操作

    Oracle对表的基本Curd操作: 样式表:        接下来对这张(表明:Stud)表进行Curd操作(请看面SQL代码) 增加新的字段列:alter table Stud add(heigh ...

  2. day65 django进阶(1)

    目录 一.聚合查询与分组查询 1 聚合查询(aggregate) 2 分组查询(annotate) 二.F与Q查询 1 F查询的三个功能 1.1 能帮助我们直接获取到表中某个字段对应的数据 1.2 获 ...

  3. day29 继承

    目录 一.property装饰器 应用场景1 应用场景2 应用场景3(场景2优化) 二.继承介绍 1 语法 2 属性查找 3 继承的实现原理 3.1 菱形问题 3.2 继承原理 3.3 深度优先和广度 ...

  4. 【Python篇】工厂模式

    工厂方法模式 前言 在<设计模式>一书中工厂模式提到了: 工厂方法模式(Factory Method) 抽象工厂模式 (Abstract Factory) 但是在实际过程中还有一种工厂模式 ...

  5. JavaScript学习 Ⅲ

    六. 面向对象 对象属于一种复合的数据类型,在对象中可以保存多个不同的数据类型的属性. 对象分类 内建对象 由ES标准种定义的对象.比如:Math String Number 宿主对象 由JS的运行环 ...

  6. python 装饰器(三):装饰器实例(一)

    示例 7-15 定义了一个装饰器,它会在每次调用被装饰的函数时计时,然后把经过的时间.传入的参数和调用的结果打印出来.示例 7-15 一个简单的装饰器,输出函数的运行时间 import time de ...

  7. scrapy 源码解析 (二):启动流程源码分析(二) CrawlerProcess主进程

    CrawlerProcess主进程 它控制了twisted的reactor,也就是整个事件循环.它负责配置reactor并启动事件循环,最后在所有爬取结束后停止reactor.另外还控制了一些信号操作 ...

  8. redis(十二):Redis 集合(Set)

    Redis 集合(Set) Redis 的 Set 是 String 类型的无序集合.集合成员是唯一的,这就意味着集合中不能出现重复的数据. Redis 中集合是通过哈希表实现的,所以添加,删除,查找 ...

  9. Vue全家桶之一Vue(基础知识篇)

    全家桶:Vue本身.状态管理.路由.   异步组件:     

  10. NIO实践-HTTP交互实现暨简版Tomcat交互内核

    今天就NIO实现简单的HTTP交互做一下笔记,进而来加深Tomcat源码印象. 一.关于HTTP 1.HTTP的两个显著特点,HTTP是一种可靠的超文本传输协议 第一.实际中,浏览器作为客户端,每次访 ...