本文共 2849 字,大约阅读时间需要 9 分钟。
在从零实现AOP(面向切面编程)过程中,我们不得不频繁地进行大量反射操作。尽管在.NET Core中,反射的性能经过了显著优化,但为了追求极致性能,我们自己实现了一部分反射的替代方案,包括构造器调用、方法调用、字段读写、属性读写以及特性读取等。在重构过程中,将反射扩展操作封装到独立的项目中,以便更好地方便自己和其他开发者使用。
通过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);
性能测试结果显示,Reflect的反射调用比原生反射和硬编码调用性能优越:
| 方法 | 平均值 (ns) | 标准差 (ns) | 标准误 (ns) | 错误率 (%) | 操作次数 (Op/s) | 生成次数 | 内存分配 (B) |
|---|---|---|---|---|---|---|---|
| Reflection | 119.505 | 0.4814 | 0.1243 | 8,367,831.8 | 0.0074 | 24 | |
| Reflector | 8.990 | 0.0377 | 0.0097 | 111,236,649.9 | 0.0076 | 24 | |
| Native | 3.825 | 0.0580 | 0.0150 | 261,404,148.5 | 0.0076 | 24 |
方法反射扩展通过MethodReflector作为入口,使用方式类似于System.Reflection.MethodInfo:
var typeInfo = typeof(MethodFakes).GetTypeInfo();var method = typeInfo.GetMethod("Call");var reflector = method.GetReflector();reflector.Invoke(instance, args); 性能测试结果:
| 方法 | 平均值 (ns) | 标准差 (ns) | 标准误 (ns) | 错误率 (%) | 操作次数 (Op/s) |
|---|---|---|---|---|---|
| Native_Call | 1.0473 | 0.0050 | 0.0015 | 954,874,046.8 | |
| Reflection_Call | 91.9543 | 0.3311 | 0.0855 | 10,874,961.4 | |
| Reflector_Call | 7.1544 | 0.0587 | 0.0152 | 139,774,408.3 |
属性反射扩展通过PropertyReflector作为入口,使用方式类似于System.Reflection.PropertyInfo:
var property = typeof(PropertyFakes).GetTypeInfo().GetProperty("Property");var reflector = property.GetReflector();var value = reflector.GetValue(instance); 性能测试结果:
| 方法 | 平均值 (ns) | 标准差 (ns) | 标准误 (ns) | 错误率 (%) | 操作次数 (Op/s) | 生成次数 | 内存分配 (B) |
|---|---|---|---|---|---|---|---|
| Native_Get_Property | 1.178 | 0.0229 | 0.0059 | 848,858,716.1 | - | 0 | |
| Reflection_Get_Property | 103.028 | 0.2074 | 0.0535 | 9,706,088.1 | - | 0 | |
| Reflector_Get_Property | 4.172 | 0.0172 | 0.0046 | 239,694,827.7 | - | 0 | |
| Native_Set_Property | 2.002 | 0.0114 | 0.0030 | 499,447,543.5 | - | 0 | |
| Reflection_Set_Property | 188.313 | 0.5002 | 0.1292 | 5,310,298.0 | 0.0203 | 64 | |
| Reflector_Set_Property | 5.878 | 0.0219 | 0.0056 | 170,138,324.7 | - | 0 |
通过MethodReflector获取方法上的特性示例:
var method = type.GetMethod("Method");var reflector = method.GetReflector();var attribute1 = reflector.GetCustomAttribute(typeof(Attribute1));var attributes = reflector.GetCustomAttributes(); 性能测试结果:
| 方法 | 平均值 (ns) | 标准差 (ns) | 标准误 (ns) | 错误率 (%) | 操作次数 (Op/s) |
|---|---|---|---|---|---|
| Reflection_GetCustomAttribute | 4,642.13 | 0.2289 | 744 B | 215,418.5 | |
| Reflector_GetCustomAttribute | 35.52 | 0.0101 | 32 B | 28,154,302.3 | |
| Reflection_GetCustomAttributes_WithAttrType | 5,354.49 | 0.3281 | 1,048 B | 186,759.2 | |
| Reflector_GetCustomAttributes_WithAttrType | 168.61 | 0.0710 | 224 B | 5,930,816.1 | |
| Reflection_GetCustomAttributes_All | 7,915.45 | 0.5035 | 1,632 B | 126,335.2 | |
| Reflector_GetCustomAttributes_All | 98.36 | 0.0737 | 232 B | 10,166,253.6 | |
| Reflection_IsDefined | 1,723.30 | 0.0801 | 256 B | 580,283.6 | |
| Reflector_IsDefined | 35.55 | - | 0 B | 28,126,759.1 |
可以从上述测试结果可以看出,AspectCore.Extension.Reflection在性能上均比原生反射实现有2个数量级的提升,达到了与硬编码调用相当的性能水平。尤其是在特性获取方面,优化效果最为显著。
转载地址:http://tjvyz.baihongyu.com/