究竟是什么可以比反射还快实现动态调用?| Source Generators版
前言
最近在公众号上看到一篇文章《究竟是什么可以比反射还快实现动态调用?》,它使用的是Newbe.ObjectVisitor
,基于C#表达式树访问一个普通class的所有属性和对应的值,可以拥有比直接使用反射快上10倍的性能。
就这一需求来说,我认为Source Generators
应该会更快,因为访问代码在编译时而不是运行时就生成了。
事实也验证了确实如此:
实现
这次我们使用第三方开发的Source Generators
类库来实现。
1.引用Nuget包
创建示例控制台程序,引用如下Nuget包:
AOPMethodsCommon
AOPMethodsGenerator
2.设置Attribute
在需要动态调用的类上声明Attribute:
[AutoMethods(template = TemplateMethod.CustomTemplateFile, CustomTemplateFileName = "template.txt")]
public class Yueluo
3.代码模板
添加template.txt
,用在Source Generators生成动态调用代码的模板.
内容如下:
using System;
using System.Collections.Generic;
using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;
namespace {{NamespaceName}} {public static class {{ClassName}}Extentions{public static string ValueStringProperty(this {{ClassName}} obj, string val){{{~ for mi in Properties ~}}{{~ if( mi.ReturnType == "string" ) ~}}if(string.Compare("{{mi.Name}}",val,StringComparison.CurrentCultureIgnoreCase)==0) {return obj.{{mi.Name}};}{{~ end ~}}{{~ end ~}}throw new ArgumentException("cannot find "+ val);}public static int ValueIntProperty(this {{ClassName}} obj, string val){{{~ for mi in Properties ~}}{{~ if( mi.ReturnType == "int" ) ~}}if(string.Compare("{{mi.Name}}",val,StringComparison.CurrentCultureIgnoreCase)==0) {return obj.{{mi.Name}};}{{~ end ~}}{{~ end ~}}throw new ArgumentException("cannot find "+ val);}public static object ValueProperty(this {{ClassName}} obj, string val){{{~ for mi in Properties ~}}if(string.Compare("{{mi.Name}}",val,StringComparison.CurrentCultureIgnoreCase)==0) {return obj.{{mi.Name}};}{{~ end ~}}throw new ArgumentException("cannot find "+ val);}}
}
模板使用了scriban进行解析,具体语法详见:https://github.com/scriban/scriban/blob/master/doc/language.md
以ValueStringProperty
方法举例来说:
public static string ValueStringProperty(this {{ClassName}} obj, string val){{{~ for mi in Properties ~}}{{~ if( mi.ReturnType == "string" ) ~}}if(string.Compare("{{mi.Name}}",val,StringComparison.CurrentCultureIgnoreCase)==0) {return obj.{{mi.Name}};}{{~ end ~}}{{~ end ~}}throw new ArgumentException("cannot find "+ val);
}
遍历类的所有属性(Properties),判断当前属性返回类型(mi.ReturnType)是string
,则返回对应属性名的值。
4.使用
下面是Benchmark测试代码,分别使用了Newbe.ObjectVisitor
和Source Generators
:
[Benchmark]
public string GetterString()=> ValueGetter<Yueluo, string, string>.GetGetter(_nameProperty).Invoke(_yueluo);[Benchmark]
public int GetterInt()=> ValueGetter<Yueluo, int, int>.GetGetter(_ageProperty).Invoke(_yueluo);[Benchmark]
public string GetterString2()
{ return _yueluo.ValueStringProperty("Name");
}[Benchmark]
public int GetterInt2()
{return _yueluo.ValueIntProperty("Age");
}
可以看到,Source Generators
生成的代码可读性更高。
结论
对于编译时可生成的功能,尽量使用Source Generators
实现,可以达到更好的性能和可读性。
如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“
究竟是什么可以比反射还快实现动态调用?| Source Generators版相关推荐
- 究竟是什么可以比反射还快实现动态调用?
戏精分享 C#表达式树,第一季正式完稿 前不久,我们发布了<只要十步,你就可以应用表达式树来优化动态调用>. 观众们普遍反映文章的内容太多复杂不太容易理解. 因此,我们以此为契机发布了&l ...
- 揭秘 ClownFish 比手写代码还快的原因
说明:本文的第一版由于反对人数较多(推荐/反对数量是:23 / 17), 我在8月20日删除了博文内容,只留下一段简单的内容. 既然分享技术也引来这么多的反对,那我就不分享了. 如果希望知道我的优化方 ...
- 在M1芯片上跑原生Linux:编译速度比macOS还快40%,真香警告
Alex 发自 凹非寺 量子位 | 公众号 QbitAI 现在,M1 Mac可以顺利运行原生Linux了. 专为苹果自研芯片打造的Asahi Linux项目,Alpha版本已经释出. 在Mac采用英特 ...
- 比反射更快:委托 第3部分
目录 泛型方法 静态泛型方法 实例泛型方法 事件 事件添加访问器 事件删除访问者 总结 现在是时候介绍以下成员了. 泛型方法 事件 泛型方法 以前我们没有介绍C#关于方法的非常重要的特性.如果您阅读本 ...
- 比反射更快:委托 第2部分
目录 构造函数 静态方法 实例方法 总结 GitHub和Nuget包中提供了具有新功能和错误修复的代码. 现在是时候介绍以下成员了.(如想了解字段.属性等情况,可查看上一篇文章) 静态的 方法 例 方 ...
- 比反射更快:委托 第1部分
目录 为什么不用反射? 委托一切 静态属性 获取访问器(get accessors) 设置访问器(set accessors) 改进 属性 改进 索引器 改进 Setters 静态字段 获取静态字段值 ...
- python下载哪个版本好-究竟哪个版本的Python是最快的?
作者|Anthony Shaw 编辑|安翔 Python 3 比 Python 2 慢吗?哪个版本的 Python 3 速度最快?还有哪些措施可以提高速度?究竟哪个版本的 Python 是最快的?当然 ...
- ClownFish:比手写代码还快的通用数据访问层
最近花了二个月的业余时间重写了我以前的通用数据访问层, 由于是重写,所以我给这个项目取了个新名字:ClownFish 如果需要了解ClownFish的使用方法,请点击ClownFish 使用说明 Cl ...
- vc的速度有c语言快吗,大家帮看看,怎么回事?Delphi竟比vc++还快
已结贴√ 问题点数:20 回复次数:15 大家帮看看,怎么回事?Delphi竟比vc++还快 前天有一个求素数个数问题,用delphi7.0求得100000000以内素数用时21.234秒,为想更快一 ...
最新文章
- 厉害!从电影花瓶到 Wi-Fi 之母,这才是乘风破浪的姐姐!
- 【送】VMware 虚拟化知识思维导图
- sas中的sql(2) 行选择 、限制重复、条件运算符、运行前语法检查、feedback、count...
- 【Python数据挖掘课程】七.PCA降维操作及subplot子图绘制
- javaweb学习6——自定义标签
- C++实用技巧(一) - λ-calculus(惊愕到手了欧耶,GetBlogPostIds.aspx) - C++博客
- C 多态和java多态_C与java的多态机制与区别
- python generator iterator_Python:Iterator、Generator和Yield总结
- java的人patch方法_java – Spring MVC PATCH方法:部分更新
- ios中获取各种文件的目录路径方法
- 区块链 智能合约是有状态的吗
- 破B操作系统:(1)显示桌面图标
- 0基础学RS(二十五)思科OSPF配置
- 写给没时间理财的上班族
- 计算机考研基本信息,复旦大学计算机考研基本信息
- 【2022新版】Java 终极学习路线(文末高清大图)-共计9大模块/6大框架/13个中间件
- SLAM总结(二)-数学基础之求导和线性方程求解
- 性能测试领域:你知道的越多,不知道的也就越多
- 一种改进的鲸鱼优化算法
- (附源码)计算机毕业设计SSM智慧停车系统
热门文章
- application/x-www-form-urlencoded 与multipart/form-data
- 加快网站访问速度--jquery.js
- 在Win7中怎样打开摄像头?
- 【转载】 quartus中调用modelsim仿真的方法
- 在类中用class时数据是共有还是私有_jvm学习笔记之class文件的加载、初始化
- 高精度(压位+判负数+加减乘+读写)
- webjars管理静态资源
- 三星笔记本进入BIOS后找不到U盘启动项/快速启动键F12没有反应
- 使用命令导入、导出mysql数据
- Github上影响力最大的十位Pythoner