在从零实现AOP的过程中,难免会需要大量反射相关的操作,虽然在.net 4.5+/.net core中反射的性能有了大幅的优化,但为了追求极致性能,自己实现了部分反射的替代方案,包括构造器调用、方法调用、字段读写,属性读写和特性读取。在重构时,把反射扩展操作封装到单独的项目AspectCore.Extension.Reflection中,以此方便自己和大家使用。

获取AspectCore.Extension.Reflection

通过nuget获取AspectCore.Extension.Reflection

    Install-Package AspectCore.Extensions.Reflection -pre

构造器反射扩展

提供ConstructorReflector作为构造器反射扩展的入口,使用方式类似System.Reflection.ConstructorInfo:

var constructorInfo = typeof(ConstructorFakes).GetTypeInfo().GetConstructor(new Type[0]);
var reflector = constructorInfo.GetReflector();
var instance = reflector.Invoke(args);

性能测试(Reflection为.NET Core提供的反射调用,Reflector为AspectCore.Extension.Reflection调用,Native为硬编码调用,下同):

 |     Method |       Mean |     Error |    StdDev |    StdErr |          Op/s |  Gen 0 | Allocated |
|----------- |-----------:|----------:|----------:|----------:|--------------:|-------:|----------:|
| Reflection | 119.505 ns | 0.5146 ns | 0.4814 ns | 0.1243 ns | 8,367,831.8 | 0.0074 | 24 B |
| Reflector | 8.990 ns | 0.0403 ns | 0.0377 ns | 0.0097 ns | 111,236,649.9 | 0.0076 | 24 B |
| Native | 3.825 ns | 0.0620 ns | 0.0580 ns | 0.0150 ns | 261,404,148.5 | 0.0076 | 24 B |

方法调用反射扩展

提供MethodReflector作为方法反射扩展的入口,使用方式类似System.Reflection.MethodInfo

var typeInfo = typeof(MethodFakes).GetTypeInfo();
var method = typeInfo.GetMethod("Call");
var refector = method.GetReflector();
refector.Invoke(instance,args);

性能测试:

 |             Method |        Mean |     Error |    StdDev |    StdErr |            Op/s |
|------------------- |------------:|----------:|----------:|----------:|----------------:|
| Native_Call | 1.0473 ns | 0.0064 ns | 0.0050 ns | 0.0015 ns | 954,874,046.8 |
| Reflection_Call | 91.9543 ns | 0.3540 ns | 0.3311 ns | 0.0855 ns | 10,874,961.4 |
| Reflector_Call | 7.1544 ns | 0.0628 ns | 0.0587 ns | 0.0152 ns | 139,774,408.3 |

属性调用反射扩展

提供PropertyReflector作为属性反射扩展的入口,使用方式类似System.Reflection.PropertyInfo

var property  = typeof(PropertyFakes).GetTypeInfo().GetProperty("Property");
var reflector = property.GetReflector();
var value = reflector.GetValue(instance);

性能测试:

 |                    Method |       Mean |     Error |    StdDev |    StdErr |          Op/s |  Gen 0 | Allocated |
|-------------------------- |-----------:|----------:|----------:|----------:|--------------:|-------:|----------:|
| Native_Get_Property | 1.178 ns | 0.0244 ns | 0.0229 ns | 0.0059 ns | 848,858,716.1 | - | 0 B |
| Reflection_Get_Property | 103.028 ns | 0.2217 ns | 0.2074 ns | 0.0535 ns | 9,706,088.1 | - | 0 B |
| Reflector_Get_Property | 4.172 ns | 0.0194 ns | 0.0172 ns | 0.0046 ns | 239,694,827.7 | - | 0 B |
| Native_Set_Property | 2.002 ns | 0.0122 ns | 0.0114 ns | 0.0030 ns | 499,447,543.5 | - | 0 B |
| Reflection_Set_Property | 188.313 ns | 0.5347 ns | 0.5002 ns | 0.1292 ns | 5,310,298.0 | 0.0203 | 64 B |
| Reflector_Set_Property | 5.878 ns | 0.0234 ns | 0.0219 ns | 0.0056 ns | 170,138,324.7 | - | 0 B |

特性获取扩展

以获取方法上标记的特性为例。

方法定义如下:

 [Attribute1]
[Attribute2("benchmark", Id = 10000)]
[Attribute3]
[Attribute3]
[Attribute3]
public void Method()
{
}

使用MethodReflector来获取特性:

var method = type.GetMethod("Method");
var reflector = method.GetReflector();
var attribute1 = reflector.GetCustomAttribute(typeof(Attribute1));
var attributes = reflector.GetCustomAttributes();

性能测试:

 |                                      Method |        Mean |         Op/s |  Gen 0 | Allocated |
|-------------------------------------------- |------------:|-------------:|-------:|----------:|
| Reflection_GetCustomAttribute | 4,642.13 ns | 215,418.5 | 0.2289 | 744 B |
| Reflector_GetCustomAttribute | 35.52 ns | 28,154,302.3 | 0.0101 | 32 B |
| Reflection_GetCustomAttributes_WithAttrType | 5,354.49 ns | 186,759.2 | 0.3281 | 1048 B |
| Reflector_GetCustomAttributes_WithAttrType | 168.61 ns | 5,930,816.1 | 0.0710 | 224 B |
| Reflection_GetCustomAttributes_All | 7,915.45 ns | 126,335.2 | 0.5035 | 1632 B |
| Reflector_GetCustomAttributes_All | 98.36 ns | 10,166,253.6 | 0.0737 | 232 B |
| Reflection_IsDefined | 1,723.30 ns | 580,283.6 | 0.0801 | 256 B |
| Reflector_IsDefined | 35.55 ns | 28,126,759.1 | - | 0 B |

可以看到AspectCore.Extension.Reflection在性能上都比反射有2个数量级的优化,达到了和硬编码调用相同的数量级。尤其是获取特性的优化最为明显。

可以在Github获取详细的性能测试。

Github : https://github.com/dotnetcore/AspectCore-Framework

AspectCore Group QQ群: 306531723

AspectCore.Extension.Reflection : .NET Core反射扩展库的更多相关文章

  1. ServiceStack.Redis 的 ASP.NET Core 扩展库

    给大家安利一款 ServiceStack.Redis 的 ASP.NET Core 扩展库,它是基于 ServiceStack.Redis.Core 开发的. 简单易用,开源免费,使用ASP.NET ...

  2. Log4net 的 ASP.NET Core 扩展库

    给大家安利一款 log4net 的 ASP.NET Core 扩展库,它是基于 log4net 开发的. 简单易用,开源免费,使用ASP.NET Core自身提供的DI容器来实现服务的注册和消费.直接 ...

  3. ASP.NET Core扩展库

    亲爱的.Neter们,在我们日复一日的编码过程中是不是会遇到一些让人烦恼的事情: 日志配置太过复杂,各种模板.参数也搞不清楚,每次都要去查看日志库的文档,还需要复制粘贴一些重复代码,好无赖 当需要类型 ...

  4. ASP.NET Core扩展库之日志

        上一篇我们对Xfrogcn.AspNetCore.Extensions扩展库功能进行了简单的介绍,从这一篇文章开始,我将逐步介绍扩展库中的核心功能.     日志作为非业务的通用领域基础功能, ...

  5. ASP.NET Core扩展库之Http通用扩展

    本文将介绍Xfrogcn.AspNetCore.Extensions扩展库对于Http相关的其他功能扩展,这些功能旨在处理一些常见需求, 包括请求缓冲.请求头传递.请求头日志范围.针对HttpClie ...

  6. ASP.NET Core扩展库之Http请求模拟

    如今,完全独立的业务应用几乎不存在,不管是在企业内部微服务之间的调用,还是与外部第三方服务的调用,Http的API交互是常见的场景,这些实际情况给我们的开发带来了比较大的挑战,一是第三方服务可能会牵制 ...

  7. .Net core Worker Service 扩展库

    .Net core Worker Service 扩展库,目的为更易控制每一个worker 的运行. 提供根据配置文件对每一个Worker的停止.启动和自动解析注册Worker. 获取配置的方式不限于 ...

  8. ASP.NET Core扩展库之实体映射

    在分层设计模式中,各层之间的数据通常通过数据传输对象(DTO)来进行数据的传递,而大多数情况下,各层数据的定义结构大同小异,如何在这些定义结构中相互转换,之前我们通过使用AutoMapper库,但Au ...

  9. Z.ExtensionMethods 一个强大的开源扩展库

    今天有意的在博客园里面搜索了一下 Z.ExtensionMethods 这个扩展类库,确发现只搜到跟这个真正相关的才两篇博文而已,我都点进去看了一下,也都只是提到而已,没有专门介绍,才引起我写这篇文档 ...

随机推荐

  1. 结对编程1 —— 基于GUI和Swing的四则运算题目生成器

    合作伙伴 201421123102 王艳秋 201421123106 陈 雄 代码地址 题目描述 我们在个人作业1中,用各种语言实现了一个命令行的四则运算小程序.进一步,本次要求把这个程序做成GUI( ...

  2. 201521123082 《Java程序设计》第5周学习总结

    201521123082 <Java程序设计>第5周学习总结 标签(空格分隔): java 1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规 ...

  3. 团队作业八—第二次团队冲刺(Beta版本) 第 1 天

    一.每个人的工作 (1) 昨天已完成的工作 由于是才刚开始冲刺,所以没有昨天的工作 (2) 今天计划完成的工作: 对界面的优化和一些细节的完善 (3) 工作中遇到的困难: 工作中出现了意见不一的情况 ...

  4. 关于在git添加远程地址的过程中遇到的问题

    问题产生的过程 我根据菜鸟教程的步骤,做了如下操作: 1.打开安装文件夹中的git-bash程序 2.设置username和email 3.添加远程地址 结果如下: 之后通过百度知道要先git ini ...

  5. 团队作业4——第一次项目冲刺(Alpha版本) 4.24

    团队作业4--第一次项目冲刺(Alpha版本) Day four: 会议照片 每日站立会议: 项目进展 今天是项目的Alpha敏捷冲刺的第三天,先大概整理下昨天已完成的任务以及今天计划完成的任务.今天 ...

  6. 201521123058 java第六次作业

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 2. 书面作业 1.clone方法 1.1 Object对 ...

  7. tsst

    import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Sc ...

  8. thinkphp介绍及访问方式

    ThinkPHP框架 1.解压到www目录下,里面有一个index文件是入口文件,通过修改里面的APP_PATH进入不同的应用 2.ThinkPHP文件夹是核心文件夹,里面东西不要修改,可以查看,比如 ...

  9. 安装wampserve之前需要安装vc++2012.

    本人是64位系统下载了wampserver3.0.6之后安装好,启动报错缺少msvcr110.dll. 于是从网上下载了msvcr110.dll放到了windows的syswow64文件夹下,甚至还重 ...

  10. ThreadLocal原理及使用示例

    简介:本文已一个简要的代码示例介绍ThreadLocal类的基本使用方式,在此基础上结合图片阐述它的内部工作原理. 欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblog ...