C# 9 新特性:代码生成器、编译时反射

前言

今天 .NET 官方博客宣布 C# 9 Source Generators 第一个预览版发布,这是一个用户已经喊了快 5 年特性,今天终于发布了。

简介

Source Generators 顾名思义代码生成器,它允许开发者在代码编译过程中获取查看用户代码并且生成新的 C# 代码参与编译过程,并且可以很好的与代码分析器集成提供 Intellisense、调试信息和报错信息,可以用它来做代码生成,因此也相当于是一个加强版本的编译时反射。

使用 Source Generators,可以做到这些事情:

  • 获取一个 Compilation 对象,这个对象表示了所有正在编译的用户代码,你可以从中获取 AST 和语义模型等信息

  • 可以向 Compilation 对象中插入新的代码,让编译器连同已有的用户代码一起编译

Source Generators 作为编译过程中的一个阶段执行:

编译运行 -> [分析源代码 -> 生成新代码] -> 将生成的新代码添加入编译过程 -> 编译继续。

上述流程中,中括号包括的内容即为 Source Generators 所参与的阶段和能做到的事情。

作用

.NET 明明具备运行时反射和动态 IL 织入功能,那这个 Source Generators 有什么用呢?

编译时反射 - 0 运行时开销

拿 ASP.NET Core 举例,启动一个 ASP.NET Core 应用时,首先会通过运行时反射来发现 Controllers、Services 等的类型定义,然后在请求管道中需要通过运行时反射获取其构造函数信息以便于进行依赖注入。然而运行时反射开销很大,即使缓存了类型签名,对于刚刚启动后的应用也无任何帮助作用,而且不利于做 AOT 编译。

Source Generators 将可以让 ASP.NET Core 所有的类型发现、依赖注入等在编译时就全部完成并编译到最终的程序集当中,最终做到 0 运行时反射使用,不仅利于 AOT 编译,而且运行时 0 开销。

除了上述作用之外,gRPC 等也可以利用此功能在编译时织入代码参与编译,不需要再利用任何的 MSBuild Task 做代码生成啦!

另外,甚至还可以读取 XML、JSON 直接生成 C# 代码参与编译,DTO 编写全自动化都是没问题的。

AOT 编译

Source Generators 的另一个作用是可以帮助消除 AOT 编译优化的主要障碍。

许多框架和库都大量使用反射,例如System.Text.Json、System.Text.RegularExpressions、ASP.NET Core 和 WPF 等等,它们在运行时从用户代码中发现类型。这些非常不利于 AOT 编译优化,因为为了使反射能够正常工作,必须将大量额外甚至可能不需要的类型元数据编译到最终的原生映像当中。

有了 Source Generators 之后,只需要做编译时代码生成便可以避免大部分的运行时反射的使用,让 AOT 编译优化工具能够更好的运行。

例子

INotifyPropertyChanged

写过 WPF 或 UWP 的都知道,在 ViewModel 中为了使属性变更可被发现,需要实现 INotifyPropertyChanged 接口,并且在每一个需要的属性的 setter 处除法属性更改事件:

当属性多了之后将会非常繁琐,先前 C# 引入了 CallerMemberName 用于简化属性较多时候的情况:

即,用 CallerMemberName 指示参数,在编译时自动填充调用方的成员名称。

但是还是不方便。

如今有了 Source Generators,我们可以在编译时生成代码做到这一点了。

为了实现 Source Generators,我们需要写个实现了 ISourceGenerator 并且标注了 Generator 的类型。

完整的 Source Generators 代码如下:

有了上述代码生成器之后,以后我们只需要这样写 ViewModel 就会自动生成通知接口的事件触发调用:

上述代码将会在编译时自动生成以下代码参与编译:

非常方便!

使用时,将 Source Generators 部分作为一个独立的 .NET Standard 2.0 程序集(暂时不支持 2.1),用以下方式引入到你的项目即可:

限制

Source Generators 仅能用于访问和生成代码,但是不能修改已有代码,这有一定原因是出于安全考量。

文档

Source Generators 处于早期预览阶段,docs.microsoft.com 上暂时没有相关文档,关于它的文档请访问在 roslyn 仓库中的文档:

设计文档

使用文档

后记

目前 Source Generators 仍处于非常早期的预览阶段,API 后期还可能会有很大的改动,因此现阶段不要用于生产。

另外,关于与 IDE 的集成、诊断信息、断点调试信息等的开发也在进行中,请期待后续的 preview 版本吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310246.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

I/O性能与可靠性

I/O调优 磁盘I/O优化 性能检测: 压力测试应用程序,观察系统I/O wait指标是否正常,例如有n个CPU,利息情况下I/O wait参数不超过25%,如果超过,就是这个程序的瓶颈就是在IO操作上了可以用iostat命令查看另外…

.NET开源工具类库:Masuit.Tools

【开源框架】| 通用工具类库这是恰童鞋骚年的第223篇原创文章本文介绍一个我的同事【懒得勤快】(人称勤快哥,我们叫他骚哥)写的一个.NET开源工具类库项目,包含一些常用的操作类,大都是静态类,加密解密&…

[Java基础]字节,字符打印流

代码如下: package PrintWriterPack;import java.io.FileNotFoundException; import java.io.PrintWriter;public class PrintWriterDemo {public static void main(String[] args) throws FileNotFoundException {PrintWriter pw new PrintWriter("D:\\Java…

javaI/O包中的包装模式

设计模式解析–适配器模式 对适配器模式功能比较好理解,就是讲一个类的接口换成客户端所能接受的另外一个接口,从而使两国接口不匹配而无法在一起工作的两个类能在一起工作。 适配器的结构 适配器UML图如下 Target(目标接口)&…

DevOps vs. Agile:它们有什么共同点?

导语DevOps与Agile有很多不同,但它们之间仍可发现很多共同点,这篇文章为读者揭晓。正文DevOps和Agile之间有着明显的关系。Agile是方法论,Scrum是框架,并DevOps随着看板也落在了Agile的“伞”下。精益,大规模的Scrum&a…

[Java基础]Properties

代码如下: package PropertiesPack;import java.util.Properties; import java.util.Set;public class PropertiesDemo01 {public static void main(String[] args){Properties prop new Properties();prop.put("001","Tom");prop.put("002",&…

空心点_空心砖的新玩法,看完大开眼界

我们所见的空心砖大都在建筑工地上常见的有水泥空心砖和粘土空心砖特点是轻质、环保、保温和隔音如此常见的空心砖仅仅是只为建筑而生吗不是,不管是古朴砖红色空心砖,还是高冷的水泥空心砖他们可以演绎不同的角色甚至让每个渴望回归本真的我们&#xff0…

IO与零拷贝

IO与零拷贝 零拷贝基本介绍 零拷贝时网络编程的一个关键优化点在Java程序中,常用的零拷贝又mmap(内存映射)和sendFile。那么在OS中的设计时如何,我们需分析mmap和sendFile对比最后通过案例分析 用户进程与操作系统关系 我们先…

从堆里找回“丢失”的代码

前言 前一阵子,使用小乌龟(TortoiseGit)提交代码的时候,错误的 Revert 了部分代码,本文记录了找回这部分代码的过程。文章标题致敬张银奎老师《格蠹汇编》的第一章 —— 从堆里抢救丢失的博客。说明: 本文的…

[Java基础]线程基础与实现多线程

代码如下&#xff1a; package MyThreadPack;public class MyThread extends Thread {Overridepublic void run() {for (int i 0;i<100;i){System.out.println(i);}} }package MyThreadPack;public class MyThreadDemo01 {public static void main(String[] args){MyThrea…

gpio 树莓派3a+_树莓派4上市:性能飙升起售价依然是35美元

旨在通过超实惠方式&#xff0c;鼓励孩子们投身编程事业的奇趣开发套件树莓派&#xff0c;在昨天迎来了Raspberry Pi 4正式开售的消息。新一代树莓派引入64位处理器、802.11ac双频Wi-Fi以及通过HAT的以太网供电(PoE)等新卖点。树莓派Raspberry Pi 4的处理能力是前一代的三倍、多…

入门级微单反性能对比

入门级相机筛选 先说挑选规则 由于微单体型小于单反&#xff0c;所以在机型选择上微单&#xff1e;单反&#xff1b;最好具备翻转屏和触摸屏&#xff1b;机身防抖不是刚需&#xff0c;但能解决小范围抖动情况下稳定问题&#xff1b;自动对焦很重要&#xff0c;眼控对焦是加分…

知识更新越来越快,但是学习起来越来越困

大家好&#xff0c;我是Z哥&#xff0c;先祝大家节日快乐。不知道这个假期你打算出门吗&#xff1f;Z哥我是打算不出远门了&#xff0c;怕死&#xff0c;哈哈。索性好好宅家里学习&#xff0c;强化一下自己。相信大家也感受到了&#xff0c;随着互联网加速了信息的流动速度&…

什么标准规定了aes加密_Python 爬虫进阶必备 | 关于某租房网站数据加密的分析(送两本 Python 书)...

关于某租房网站数据加密的分析aHR0cHM6Ly93d3cubWFvbWFvenUuY29tLw抓包分析先看看这个网站的首页数据可以看到首页的 html 是压缩的&#xff0c;但是格式化之后没有看到需要的首页数据。过滤 xhr 请求看到一个 index.json的请求可以看到这个请求的请求参数以及返回值都是密文返…

[Java基础]线程同步之卖票案列分析

案列: 卖票。 需求: 某电影院目前正在上映国产大片&#xff0c;共有100张票&#xff0c;而它有3个窗口卖票&#xff0c;请设计一个程序模拟该电影院卖票。 代码如下: package SellTicketPack;public class SellTicket implements Runnable{private int tickets 100;Overrid…

sap 标准委外和工序委外_SAP FICO零基础学习_0035_标准成本估算-主数据-物料主数据...

前辈的第35堂课&#xff1a;谢谢大家的喜欢和关注噢~这里的“前辈”其实指的是给我讲课的前辈啦&#xff0c;我不是前辈噢&#xff0c;我只是一个刚刚接触FICO的小白&#xff0c;跟大家分享前辈给我讲的东西。因为刚接触&#xff0c;学习的内容比较简单~有基础的小伙伴可以去看…

[Java基础]线程安全的类

package ThreadDemoPack01;import java.util.*;public class ThreadDemo01 {public static void main(String[] args){StringBuffer sb new StringBuffer();//线程安全StringBuilder sb2 new StringBuilder();//线程不安全Vector<String> v new Vector<String>(…

数据结构与算法-- 八皇后问题(多种实现方案)

八皇后问题解法一(排列筛选法) 本篇我们承接上一篇中的思想&#xff0c;想到了一个经典的算法题&#xff0c;八皇后问题&#xff1a;题目&#xff1a;在8*8的国际象棋上摆放8个皇后&#xff0c;使得其互相不能攻击&#xff0c;即任意两个换后不能在同一行&#xff0c;同一列&a…

Blazor WebAssembly 3.2.0 正式起飞,blazor 适合你吗?

最近blazor更新很快&#xff0c;今天在官方博客上发布了Blazor WebAssembly 3.2.0 RC&#xff1a;https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-release-candidate-now-available/ &#xff0c;这是最后一次预览版了&#xff0c;功能开发都已经完成。5.19的…

中获取文件名不要扩展名_如何批量修改文件名,3s时间够不够

?点击关注Excel表哥公众号上一篇推文我们介绍了如何批量获取同一文件夹下所有的文件名。▲点此图片回顾很多读者获取到这些文件名之后的一种工作情形就是需要批量或者有针对性地修改这些文件的名称。那么但凡是这类需要批量操作的重复工作&#xff0c;Excel擅长。还是以上篇推…