项目简介

自 Natasha v9.0 发布起,我将基于 Natasha 的推出热执行方案,这项技术允许基于 控制台(Console) 和新版 Asp.net Core 架构的项目在运行中动态重编译,在不停止工程的情况下获取最新结果,以帮助技术初学者、项目初期开发人员等,进行快速实验以及试错。

为了更形象的说明 [热执行] 请看下图:

热执行

以下为了更加简洁,称热执行为 [HE].

图中是 Asp.net Core 一个接口开发的案例,我更改了一个实体类的结构,并保存,可以看到接口返回了最新的实体类结构。借此简单阐述一些热执行的工作原理,文件发生变化会触发 [HE] 对项目进行热编译,开发者无论是大改还是小改,只要你的项目文件(cs) 、依赖项目、csproj 发生了变化,[HE] 就会代理整个项目并自动编译输出。对于有些老机器较慢,可能 [HE] 热编译要比 [按下F5-程序跑起来] 要快的多。

热重载与热执行

也许有人会觉得这更像一个完全体的热重载,并不是,这是与热重载完全不同的技术,[HE] 的核心技术是语法树重写与动态编译。而热重载是对 Runtime 的程序集进行热更新,热重载严重依赖 Debugger 组件,且目前从 ENC 错误代码 来看这项技术的限制还是很大的。

起初我也是闷头钻研热重载技术,但实验效果很不理想,热重载技术是一项前沿的,边界明确的技术,并不适合敞开手脚快刀阔斧的干,由于不是面对开发者,(截至2024年8月)资料也不是很多。与其死磕它,不如另辟蹊径,借助 Natasha 动态代理将项目管理起来。

指令简介

注释指令

HE 使用注释作为热代理指令,这些指令会影响语法树重建以及热编译选项,但不影响程序的发布和使用。目前具体如下:

  • 优化级别

使用 //HE:Release 指令允许在 HE 重编译时,使用 Release 模式进行编译。

  • 异步代理

当 Main 方法中有对象 A, A 需要延迟卸载,A 不干扰 new A (即全局可以不只有一个 A), 此时使用 //HE:Async 允许 HE代理 在上一次 A 对象未完全销毁时异步执行新 Main 方法。

  • Using 排除

由于开发可能会开启隐式 using, 若开启,则 HE 在代理期间,会加载所有内存中存在的命名空间,因此有概率会出现 using 二义性引用问题,使用 //HE:CS0104 可以排除干扰 using,例如 //HE:CS0104 using1;using2...

  • 动态表达式

如果您需要在 HE 代理期间动态的调试输出一些结果,且不影响程序发布,您可以使用 //DS 或 //RS 指令输出其后的表达式。例如 //DS 1+1 在 Debug 模式下输出 2. //RS a.age+b.age 在 Release 输出两个对象年龄相加。

  • 参数传递

void ProxyMainArguments() 方法将在代理执行之前执行,该方法允许开发者在动态开发中,在 HE 代理期间模拟 控制台向 main 方法中传递参数。

伪代码类似于:

public static void ProxyMainArguments()
{
HEProxy.AppendArgs("123");
HEProxy.AppendArgs("参数2");
HEProxy.AppendArgs("abc");
}
main("123","参数2","abc");

注意:HE 每次创建新的代理都是一次全新的 main 执行过程,因此将清空 Args, 避免上一次代理干扰本次执行。

  • 仅在程序第一次运行

使用 //Once 命令允许程序仅在程序第一次开启时运行被其注释的代码,在后续的 HE 代理期间,被注释的语法节点将被剔除。

使用

目前该项目支持 .NET3.0 即以上版本,且 .NET5.0 版本以上有 Source Generator 技术加持。

无 SG 加持的版本

  1. 引入热执行包:DotNetCore.Natasha.CSharp.HotExecutor
class Program
{ public static void Main(string[] args)
{ //设置当前程序的类型 ,默认为 Console
HEProxy.SetProjectKind(HEProjectKind.Console); //HE 代理周期日志(如果不需要 HE 写入日志,这句就不用写了)
string debugFilePath = Path.Combine(VSCSProjectInfoHelper.HEOutputPath, "Debug.txt");
HEFileLogger logger = new HEFileLogger(debugFilePath); //设置信息输出方式,该方法影响 DS/RS 指令的输出方式
//默认是 Console.WriteLine 方式输出
HEProxy.ShowMessage = async msg => {
//一些项目可能禁用控制台,那就用日志输出 HE 信息
await logger.WriteUtf8FileAsync(msg);
}; //编译初始化选项,主要是 Natasha 的初始化操作.
//Once (热编译时使用 Once 剔除被注释的语句)
HEProxy.SetCompileInitAction(() => {
{
NatashaManagement.RegistDomainCreator<NatashaDomainCreator>();
NatashaManagement.Preheating((asmName, @namespace) => !string.IsNullOrWhiteSpace(@namespace) &&
(HEProxy.IsExcluded(@namespace)),
true,
true);
}
}); //开始执行动态代理.
//Once (热编译时使用 Once 剔除被注释的语句)
HEProxy.Run(); for (int i = 0; i < args.Length; i++)
{
Console.WriteLine(args[i]);
//在 HE 代理期间输出 args 值
//DS args[i]
} //while 阻塞时需要指定 CancelToken ,热执行时 HE 将取消循环操作。
CancellationTokenSource source = new CancellationTokenSource(); //添加到 HE 中,以便下个编译时释放
source.ToHotExecutor(); while (!source.IsCancellationRequested)
{
Thread.Sleep(1000);
//在 HE 代理期间输出 "In while loop!"
//DS "In while loop!"
} for (int i = 0; i < args.Length; i++)
{
Console.WriteLine(args[i]);
} //防止 while 退出后直接关闭主线程
//Once (这句 `//Once` 可以不写,HE 有针对 “Console.Read” 的末尾阻塞检测)
Console.ReadKey(); } //方法体中的参数操作对应 Main(string[] args) 中的 args,
//热执行时,Main 将接收到 "参数11",“参数2”,“参数23”
//非必要,可以不写
public static void ProxyMainArguments()
{
HEProxy.AppendArgs("参数11");
HEProxy.AppendArgs("参数2");
HEProxy.AppendArgs("参数23");
}
}

这段代码是 HE 最原始的代码。

SG 加持(.NET5.0及以上版本)

SG 主要是减少了 HE 初始化的一些操作。而一些需要手动传递的 cancel/dispose 实例仍然需要手动传递给 HE。

简单案例

  1. 引入 SG 包:DotNetCore.Natasha.CSharp.HotExecutor.Wrapper
internal class Program
{ static void Main(string[] args)
{
for (int i = 0; i < args.Length; i++)
{
//DS args[i]
} //这里仍然需要手动将 canceltoken 传递给 HE
CancellationTokenSource source = new();
source.ToHotExecutor(); while (!source.IsCancellationRequested)
{
Thread.Sleep(1000);
//DS "In while loop!"
} //防止 while 退出后直接关闭主线程
Console.ReadKey();
}
public static void ProxyMainArguments()
{
HEProxy.AppendArgs("参数1");
HEProxy.AppendArgs("参数2");
HEProxy.AppendArgs("参数3");
HEProxy.AppendArgs("参数4");
}
}

代理新 Asp.net Core

HE 目前不能代理 MVC 项目和老版的 API 项目。

public class Program
{
public static void Main(string[] args)
{ //HE:Async
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
} //将 APP 添加到 HE 中,以便在下一次编译中释放该对象。
app.AsyncToHotExecutor(); //更改以下的值,保存文件,会触发 HE 创建新的 WebApplicationBuilder
var summaries = new[]
{
"Freezing441", "Bracing"
}; app.MapGet("/weatherforecast", (HttpContext httpContext) =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
})
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast"); app.Run();
}
}

其他项目支持

截至目前而言, HE 对 Winform 的支持不是很好,WPF 的很难代理,时间和精力有限,不会深入去研究了。

鸣谢

感谢 九哥 的支持。

结尾

遇到问题可以到 Natasha Issue 区 提出反馈。

Natasha v9.0 为 .NET 开发者提供 [热执行] 方案.的更多相关文章

  1. IBM Rational Software Architect V9.0安装图解

    IBM Rational Software Architect(RSA) -- IBM软件开发平台的一部分 – 是IBM在2003年二月并购Rational以来,首次发布的Rational产品.改进过 ...

  2. Natasha 4.0 探索之路系列(一) 概况

    Natasha 简介 Natasha 是一个基于 Roslyn 的动态编译类库, 它以极简的 API 完成了动态编译的大部分功能, 使用它可以在程序运行时编译出新的程序集. Natasha 允许开发人 ...

  3. Natasha 4.0 探索之路系列(三) 基本的动态编译

    Natasha 的设计 动态编译 Roslyn 为开发者提供了动态编译的接口, 允许我们以 C# 代码来编写 Emit 或 表达式树生成的程序集, 但是完成一个编译需要诸多步骤, 用户参与的操作也很多 ...

  4. Phpwind v9.0 存储型xss跨站漏洞

    漏洞版本: Phpwind v9.0 漏洞描述: Phpwind专注于中小网站应用的整合和价值的发掘,我们认为,以社区为网站的基础,可以提供丰富的应用,满足人们获取信息.交流.娱乐.消费等生活需求.获 ...

  5. Xilinx FFT IP v9.0 使用(一)

    reference:https://blog.csdn.net/shichaog/article/details/51189711 https://blog.csdn.net/qq_36375505/ ...

  6. 微软正式发布VS2015和.Net为开发者提供数百个新功能

    今天,我很高兴地向大家宣布:Visual Studio 2015 和 .Net 4.6 的正式版本现已提供下载! 自去年十一月我们提出了微软开发技术的愿景:让所有开发者,无论他在什么平台,开发哪种应用 ...

  7. Axure9 v9.0.0.3629 ~ v9.0.0.3633 授权密钥 【2019.02.05】

    现在提供一个支持v9.0.0.3629.v9.0.0.3630.v9.0.0.3631.v9.0.0.3632.v9.0.0.3633的授权码(后续的Beta更新版本应该能继续使用) 被授权人:zd4 ...

  8. JBuss--为所有JFinal开发者提供二次开发的后台管理系统

    百度搜索:JBuss 或jfinal.com官网https://www.jfinal.com/share/1704 JBuss背景: 2018年6月1日,作者“为道日损”从上海一家xxx公司离职,那时 ...

  9. 动态编译库 Natasha 5.0 兼容版本发布

    Natasha 5.0 版本已于 2022/10/10 日发布, 此次大版本更迭带来了兼容性支持, 目前 Natasha 可以兼容 standard2.0 及 coreapp3.1 以上版本. 下载使 ...

  10. Heatmap.js v2.0 – 最强大的 Web 动态热图

    Heatmap 是用来呈现一定区域内的统计度量,最常见的网站访问热力图就是以特殊高亮的形式显示访客热衷的页面区域和访客所在的地理区域的图示.Heatmap.js 这个 JavaScript 库可以实现 ...

随机推荐

  1. ASP.NET Core – TagHelper

    前言 以前写的 Asp.net core 学习笔记之 Tag Helper, 这篇是整理版. 参考 Docs – Author Tag Helpers in ASP.NET Core Creating ...

  2. Python写入数据到MySQL数据库并读取

    1.导入pymysql库   命令行输入pip3 install PyMySQL    2.连接数据库 import pymysql db = pymysql.connect(host='localh ...

  3. 《HelloGitHub》第 102 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. github.com/521xueweihan/HelloG ...

  4. 运维管理平台OEM定制集成开发,激发IT价值

    对硬件设备商而言,借助优秀的网管.运维管理平台,可以形成完整的产品解决方案,直接提升产品的形象和适用范围.同时还可以通过网管.运维管理平台,切入到外围的产品及集成领域,并在用户后续的升级改造活动中占据 ...

  5. 2021 IT运维巡展北京站圆满落幕,北京智和信通荣获IT运维样板工程

    10月21日,以"数智转型 运维赋能"为主题的"2021(第十二届)IT运维巡展北京站"圆满落幕.会上行业专家.企业代表以及用户代表等共聚一堂,探讨数智时代下I ...

  6. Android Qcom USB Driver学习(八)

    因为要看usb charging的问题,所以需要补充一下battery的相关知识,算是入门吧 BAT SCH (1)VBATT_VSNS_P (2)BAT_THERM (3)I2C_SDA (4)I2 ...

  7. 数据库小白看这里,这个Oracle数据库知识图谱你值得拥有(含MySQL、PG图谱)

    2022年前后,墨天轮社区曾陆续推出PostgreSQL知识图谱.MySQL知识图谱,并得到了大家的广泛好评.此后,便有众多朋友对Oracle知识图谱发起不断"催更".经过近期的内 ...

  8. CodeWF.EventBus:轻量级事件总线,让通信更流畅

    1. CodeWF.EventBus EventBus(事件总线),用于解耦模块之间的通讯.本库(CodeWF.EventBus)适用于进程内消息传递(无其他外部依赖),与大家普遍使用的MediatR ...

  9. 多模型COE方法

    1.概述 在当前的人工智能发展中,单一模型的表现往往难以满足复杂任务的需求.为应对这些挑战,多模型协作的方法应运而生,"专家组合"(Mixture of Experts)便是其中一 ...

  10. 封装socket 到vue2.x 使用

    vue2.x 使用 socket 数据交互 简单封装 socket //生成唯一标识符 function getUuid { let s = []; let hexDigits = "012 ...