Natasha v4.0.0.0 动态编程新篇章

2023-11-06 05:32

本文主要是介绍Natasha v4.0.0.0 动态编程新篇章,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、简介

     

Natasha 基于 Roslyn 的 C# 动态程序集构建库,该库允许开发者在运行时使用 C# 代码构建域 / 程序集 / 类 / 结构体 / 枚举 / 接口 / 方法等,使得程序在运行的时候可以增加新的模块及功能。Natasha 集成了域管理/插件管理,可以实现域隔离,域卸载,热拔插等功能。该库遵循完整的编译流程, 可自动添加引用,完善的对象模板让开发者只专注于程序集脚本的编写,兼容 netcoreapp2.0+ / netcoreapp3.0+, 跨平台,统一、简便的链式 API。

 二、进化

Natasha 已经经历了3个大版本的迭代,从普通的编译构建到黑科技的挖掘与融入,使得 Natasha 让动态编程更加的丰富,我们相继解决了 自动覆盖引用的问题、二义性引用的问题、私有成员调用、只读字段赋值、编译环境包继承,源代码调试包继承,域/语法树/编译组件解耦等问题,暂时放弃了对 .NETFramework 的支持,希望有人能一起参与维护。

三、好处

看到有人在问,为什么需要动态编程,在回答这个问题之前我需要说明,这里我不会把动态编程细节一一展示出来,对于动态编程的见解各有春秋,从 Natasha 给我带来的收益讲一讲可能更接地气。 在 Natasha 使用  Roslyn 改造以来,我先后开源了 DeepClone 深度克隆库、NCaller 实体字段及属性代理、DynamicCache 本地高性能并发只读缓存, Lycium.Mapper 实体类映射、动态代理、动态接口、表格与实体类的相互映射等项目, 在公司项目中也使用了 Natasha, 对 NewExpression 进行了翻译处理,使得 new 表达式中的赋值操作可以被转换成结果,对所有支持表达式树的开源库来说,这是一项黑科技的切入。Natasha 在实际项目中,一出手就要见血,也许你觉得有些开源项目并不好用,那么你可以在周末使用 Natasha 花上2-3个小时定制一个项目出来, 如果你觉得2小时有点夸张,那么3个小时也够你折腾了。

四、问题

1、请问该库生成的代码性能如何?

答:原生性能,与使用者写的代码有关。

2、每次编译都要几十到几百毫秒?

答:不用每次都编译,线上项目也不是每次访问一个接口都编译一次整个项目吧, 你把编译结果缓存起来就可以了。

3、为什么每个版本的 API 都有一些变化?

答:不赚钱。

4、你开发中遇到过最多的问题是什么?

答:

穷。

贡献者太少。

脑累,因为滥用 roslyn ,第一天的问题,第二天可能就被关了。

身累,调研和实验总是在凌晨, 希望国家能出自己的编程语言。

心累,陌生人多的时候不能说自己累,会被吐槽。

5、你会反射吗?你知道反射有多牛逼吗?

答: 不太了解,谢谢科普。

6、请问 Natasha 实现的功能,反射也能做到吗?Emit 能做到吗?表达式树能做到吗?如果可以的话为啥还要用你的库?

答:能,  最后一个问题付费。

7、请问 var 是什么?

答:.....

8、请问为什么不能运行?

答:报了什么错?截图我看看。

问:这样

答:你命令敲错了,单词打错了。 

五、使用 4.0 版

1、引入 DotNetCore.Natasha v4.0

2、引入 编译组件库:

  • DotNetCore.Natasha.CSharpSyntax v2.0

  • DotNetCore.Natasha.Domain  v2.0

  • DotNetCore.Natasha.CSharpCompiler  v2.0

3、注册组件库

NatashaComponentRegister.RegistDomain<NatashaAssemblyDomain>();
NatashaComponentRegister.RegistCompiler<NatashaCSharpCompiler>();
NatashaComponentRegister.RegistSyntax<NatashaCSharpSyntax>();

4、敲代码

六、示例

  • 来这里看 HelloWorld:

https://natasha.dotnetcore.xyz/zh/helloworld.html

  • UT测试我没有写的花了呼哨,每个测试函数都是一个示例:

https://github.com/dotnetcore/Natasha/tree/v4.0+dev/test/NatashaUT

  • 直接使用字符串编译

//您可以在 AssemblyCSharpBuilder 基础上封装自己的模板
string yourClassScript = "xxx
AssemblyCSharpBuilder oop = new AssemblyCSharpBuilder();
oop.Compiler.Domain = DomainManagement.Random;
oop.Add(yourClassScript);
Type type = oop.GetTypeFromShortName("yourClass");
  • 根据字符串返回一个类:

//请把结果缓存起来
var typeMapping = new ConcurrentDictionary<string,Type>();
var str = "Student"; 
var func = NDelegate.RandomDomain().Func<Type>($"return typeof({str});");
typeMapping[str] = func();
  • 调用属性

var propNameCaller = NDelegate.RandomDomain().Func<Student,string>($"return obj.Name;");var name = propNameCaller(xxx);
  • 设置属性,但属性类型我不确定

var propNameInfo = typeof(Student).GetProperty("Name");
var propType = propNameInfo.PropertyType.GetDevelopmentName();
var propNameSetter = NDelegate.RandomDomain().Action<Student,object>($"arg1.Name = ({propType})arg2;");propNameSetter(xxx,"newName"); 
  •   创建一个类及添加成员的三种方式

NClass nClass = NClass.DefaultDomain();
nClass.Namespace("MyNamespace").Public().Name("MyClass").Ctor(ctor=>ctor.Public().Body("MyField=\"Hello\";"));
  //你可以使用 .成员()的方式来创建一个成员nClass.Property(prop => prop.Type(typeof(string)).Name("MyProperty").Public()OnlyGetter("return \"World!\";"));
//也可以单独定义成员然后添加到类中例如
MethodBuilder mb = new MethodBuilder();
mb.Public().Override().Name("ToString").Body("return MyField+\" \"+MyProperty;").Return(typeof(string));nClass.Method(mb);
//同样可以使用 nClass 创建一个 Builder 来添加成员
FieldBuilder fb = nClass.GetFieldBuilder();
fb.Public().Name("MyField").Type<string>();
  • 获取一个无参的类型构造委托

var creator = NInstance.Creator<Student>();
var creator = NInstance.Creator(typeof(Student));
Student student = creator();
  • 使用类标记访问 自定义类型的私有成员

var action = NDelegate.RandomDomain()
.SetClass(item=>item.AllowPrivate<TPropertyClass>())
.Action<TPropertyClass>("obj.privateA=1;");
action(test);
  • 使用共享库反射部分系统类型私有成员

var action = NDelegate
.RandomDomain(item => item.UseShareLibraries = true)
.SetClass(item => item.AllowPrivate<List<int>>())
.Func<int>("return (new List<int>())._size;");
var size = action();
  • 使用 Natasha 突破 readonly 赋值限制

//如果你的C#脚本代码里是这样
//  instance.Name = "xxx";  由于 Name 是只读字段会报错
//  “instance.Name”.ReadonlyScript() = "xxxx"
//使用 ReadonlyScript 扩展方法会自动对字符串包装处理成 ReadOnly 可支持的赋值类型。

七、API 说明

FastMethodOperator 是最为灵活的委托定制模板。

FakeMethodOperator 是为了仿制委托的定制模板。

NDelegate 是基于 FakeMethodOperator 封装的委托定制模板。

NClass / NEnum / NInterface / NStruct 是面向对象的定制模板。

NInstance 是实例初始化的委托模板, 目前仅支持无参构造。

八、尾语

Natasha 的黑科技建立在稳定的 Roslyn 版本之上,目前手还没有伸到深处,因此稳定性是可控的,我们拥有大量的测试与实践,同时还有线上支持,各位可以放心用。我看到网上有些文章摘抄了 Natasha 的部分代码去讲解一些应用,这里非常欢迎,希望感兴趣的老铁能进群(邮箱联系我 2765968624@qq.com),Natasha 组件已经摘出来了,所以各位都能看清楚是什么套路,欢迎大家一起做 Natasha 的贡献者,我想声明一点:开源项目没有作者,只有贡献者,谁贡献的多贡献的少的问题而已,开发者能了解这项技术,能运用,能创造便是意义所在。

Roslyn 的该用法老早已经出现,只不过对不同版本的 .NET 支持的有瑕疵,各位写文章科普和教人应用我十分欢迎,如果有其他目的:割韭菜,赚名声什么的,请停止这种行为。

下一篇将会以一个框架的实战来介绍 Natasha 。

铁子们别忘了双击666,请把 “ Natasha 最美!” 打到公屏上,谢谢。

https://github.com/dotnetcore

打赏一杯酒,削减三分愁。
跟着我们走,脱发包你有。

组织打赏账户为柠檬的账户,请标注「NCC」,并留下您的名字,以下地址可查看收支明细:https://github.com/dotnetcore/Home/blob/master/Statement-of-Income-and-Expense.md

OpenNCC,专注.NET技术的公众号

https://www.dotnetcore.xyz

微信ID:OpenNCC

长按左侧二维码关注

欢迎打赏组织

给予我们更多的支持

这篇关于Natasha v4.0.0.0 动态编程新篇章的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/354742

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

Java并发编程之——BlockingQueue(队列)

一、什么是BlockingQueue BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: 1. 当队列满了的时候进行入队列操作2. 当队列空了的时候进行出队列操作123 因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空