前言

最近在公众号上看到一篇文章《究竟是什么可以比反射还快实现动态调用?》,它使用的是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.ObjectVisitorSource 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版相关推荐

  1. 究竟是什么可以比反射还快实现动态调用?

    戏精分享 C#表达式树,第一季正式完稿 前不久,我们发布了<只要十步,你就可以应用表达式树来优化动态调用>. 观众们普遍反映文章的内容太多复杂不太容易理解. 因此,我们以此为契机发布了&l ...

  2. 揭秘 ClownFish 比手写代码还快的原因

    说明:本文的第一版由于反对人数较多(推荐/反对数量是:23 / 17), 我在8月20日删除了博文内容,只留下一段简单的内容. 既然分享技术也引来这么多的反对,那我就不分享了. 如果希望知道我的优化方 ...

  3. 在M1芯片上跑原生Linux:编译速度比macOS还快40%,真香警告

    Alex 发自 凹非寺 量子位 | 公众号 QbitAI 现在,M1 Mac可以顺利运行原生Linux了. 专为苹果自研芯片打造的Asahi Linux项目,Alpha版本已经释出. 在Mac采用英特 ...

  4. 比反射更快:委托 第3部分

    目录 泛型方法 静态泛型方法 实例泛型方法 事件 事件添加访问器 事件删除访问者 总结 现在是时候介绍以下成员了. 泛型方法 事件 泛型方法 以前我们没有介绍C#关于方法的非常重要的特性.如果您阅读本 ...

  5. 比反射更快:委托 第2部分

    目录 构造函数 静态方法 实例方法 总结 GitHub和Nuget包中提供了具有新功能和错误修复的代码. 现在是时候介绍以下成员了.(如想了解字段.属性等情况,可查看上一篇文章) 静态的 方法 例 方 ...

  6. 比反射更快:委托 第1部分

    目录 为什么不用反射? 委托一切 静态属性 获取访问器(get accessors) 设置访问器(set accessors) 改进 属性 改进 索引器 改进 Setters 静态字段 获取静态字段值 ...

  7. python下载哪个版本好-究竟哪个版本的Python是最快的?

    作者|Anthony Shaw 编辑|安翔 Python 3 比 Python 2 慢吗?哪个版本的 Python 3 速度最快?还有哪些措施可以提高速度?究竟哪个版本的 Python 是最快的?当然 ...

  8. ClownFish:比手写代码还快的通用数据访问层

    最近花了二个月的业余时间重写了我以前的通用数据访问层, 由于是重写,所以我给这个项目取了个新名字:ClownFish 如果需要了解ClownFish的使用方法,请点击ClownFish 使用说明 Cl ...

  9. vc的速度有c语言快吗,大家帮看看,怎么回事?Delphi竟比vc++还快

    已结贴√ 问题点数:20 回复次数:15 大家帮看看,怎么回事?Delphi竟比vc++还快 前天有一个求素数个数问题,用delphi7.0求得100000000以内素数用时21.234秒,为想更快一 ...

最新文章

  1. 厉害!从电影花瓶到 Wi-Fi 之母,这才是乘风破浪的姐姐!
  2. 【送】VMware 虚拟化知识思维导图
  3. sas中的sql(2) 行选择 、限制重复、条件运算符、运行前语法检查、feedback、count...
  4. 【Python数据挖掘课程】七.PCA降维操作及subplot子图绘制
  5. javaweb学习6——自定义标签
  6. C++实用技巧(一) - λ-calculus(惊愕到手了欧耶,GetBlogPostIds.aspx) - C++博客
  7. C 多态和java多态_C与java的多态机制与区别
  8. python generator iterator_Python:Iterator、Generator和Yield总结
  9. java的人patch方法_java – Spring MVC PATCH方法:部分更新
  10. ios中获取各种文件的目录路径方法
  11. 区块链 智能合约是有状态的吗
  12. 破B操作系统:(1)显示桌面图标
  13. 0基础学RS(二十五)思科OSPF配置
  14. 写给没时间理财的上班族
  15. 计算机考研基本信息,复旦大学计算机考研基本信息
  16. 【2022新版】Java 终极学习路线(文末高清大图)-共计9大模块/6大框架/13个中间件
  17. SLAM总结(二)-数学基础之求导和线性方程求解
  18. 性能测试领域:你知道的越多,不知道的也就越多
  19. 一种改进的鲸鱼优化算法
  20. (附源码)计算机毕业设计SSM智慧停车系统

热门文章

  1. application/x-www-form-urlencoded 与multipart/form-data
  2. 加快网站访问速度--jquery.js
  3. 在Win7中怎样打开摄像头?
  4. 【转载】 quartus中调用modelsim仿真的方法
  5. 在类中用class时数据是共有还是私有_jvm学习笔记之class文件的加载、初始化
  6. 高精度(压位+判负数+加减乘+读写)
  7. webjars管理静态资源
  8. 三星笔记本进入BIOS后找不到U盘启动项/快速启动键F12没有反应
  9. 使用命令导入、导出mysql数据
  10. Github上影响力最大的十位Pythoner