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

长按左侧二维码关注

欢迎打赏组织

给予我们更多的支持

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

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

相关文章

[RabbitMQ]RabbitMQ概念_四大核心概念

RabbitMQ RabbitMQ 的概念 RabbitMQ 是一个消息中间件&#xff1a;它接受并转发消息。你可以把它当做一个快递站点&#xff0c;当你要发送一个包裹时&#xff0c;你把你的包裹放到快递站&#xff0c;快递员最终会把你的快递送到收件人那里&#xff0c;按照这种逻辑 RabbitMQ …

.Net Core in Docker极简入门(下篇)

点击上方蓝字"小黑在哪里"关注我吧Docker-Compose代码修改yml fileup & down镜像仓库前言上一篇【.Net Core in Docker极简入门&#xff08;上篇&#xff09;】讲解了docker的一些基本命令和操作&#xff0c;并成功构建了自己的asp.net core web应用的镜像&#…

这么多Apache顶级项目,SkyWalking为何一枝独秀?

吴晟读完需要5分钟速读仅需 2 分钟吴晟Apache基金会会员&#xff0c;Apache SkyWalking创始人、项目VP和PMC成员&#xff0c;Apache孵化器PMC成员&#xff0c;Apache ShardingSphere PMC成员&#xff0c;Apache APISIX (incubating) PPMC成员&#xff0c;Apache ECharts (incub…

[RabbitMQ]工作原理_原理名词解释

RabbitMQ 核心部分 各个名词介绍 RabbitMQ工作原理 Broker&#xff1a; 接收和分发消息的应用&#xff0c;RabbitMQ Server 就是 Message Broker Virtual host&#xff1a; 出于多租户和安全因素设计的&#xff0c;把 AMQP 的基本组件划分到一个虚拟的分组中&#xff0c;类…

Istio 中的授权策略详解

本文节选自 ServiceMesher 社区出品的开源电子书《Istio Handbook——Istio 服务网格进阶实践》&#xff0c;阅读地址&#xff1a;https://www.servicemesher.com/istio-handbook/授权功能是 Istio 中安全体系的一个重要组成部分&#xff0c;它用来实现访问控制的功能&#xff…

[RabbitMQ]创建Java开发环境_消费者_生产者

我们将用 Java 编写两个程序。发送单个消息的生产者和接收消息并打印出来的消费者。我们将介绍 Java API 中的一些细节。 在下图中&#xff0c;“ P”是我们的生产者&#xff0c;“ C”是我们的消费者。中间的框是一个队列-RabbitMQ 代表使用者保留的消息缓冲区 引入依赖 <…

如何利用Gitlab-CI持续部署到远程机器?

长话短说&#xff0c;今天聊一聊使用Gitlab-CI 自动部署到远程服务器。如果看过《基于docker-compose的Gitlab CI/CD实践&排坑指南》这篇文章的朋友&#xff0c;会注意到我是在 Gitlab-Runner服务器上自动部署的站点&#xff0c;本次我们结合ssh部署到远程机器(将CI服务器和…

[RabbitMQ]工作队列原理_代码实现

Work Queues 工作队列(又称任务队列)的主要思想是避免立即执行资源密集型任务&#xff0c;而不得不等待它完成。 相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时&#xff0c;这些工作…

使用ImpromptuInterface反射方便的创建自定义DfaGraphWriter

在本文中&#xff0c;我为创建的自定义的DfaGraphWriter实现奠定了基础。DfaGraphWriter是公开的&#xff0c;因此您可以如上一篇文章《将终结点图添加到你的ASP.NET Core应用程序中》中所示在应用程序中使用它&#xff0c;但它使用的所有类均已标记为internal。这使得创建自己…

[RabbitMQ]消息应答概念_消息手动应答代码

消息应答 概念 消费者完成一个任务可能需要一段时间&#xff0c;如果其中一个消费者处理一个长的任务并仅只完成了部分突然它挂掉了&#xff0c;会发生什么情况。RabbitMQ 一旦向消费者传递了一条消息&#xff0c;便立即将该消 息标记为删除。在这种情况下&#xff0c;突然有…

rust火箭基地主楼开启方法_Rust 为什么能成为 Stack Overflow 最受欢迎的语言?

每年&#xff0c;开发者问答网站 Stack Overflow 都会对程序员社区展开年度调查&#xff0c;包括他们最喜爱的技术到工作偏好的所有内容。 在2017 年和2018 年Stack Overflow 年度开发者调查中&#xff0c;Rust语言已经连续两年成为最受欢迎语言Top 1。2018 年 Stack Overflow …

[RabbitMQ]队列持久化

RabbitMQ持久化 概念 如何保障当 RabbitMQ 服务停掉以后消息生产者发送过来的消息不丢失。默认情况下 RabbitMQ 退出或由于某种原因崩溃时&#xff0c;它忽视队列和消息&#xff0c;除非告知它不要这样做。确保消息不会丢失需要做两件事&#xff1a;我们需要将队列和消息都标…

微服务认证架构如何演进来的?

【答疑解惑】| 作者 / Edison Zhou这是恰童鞋骚年的第267篇原创内容之前有同事问为何要用基于JWT令牌的认证架构&#xff0c;然后近期又有童鞋在后台留言问微服务安全认证架构的实践&#xff0c;因此我决定花两篇推文来解答一下。为了答好这个话题&#xff0c;我们先来看看微服…

maskrcnn还可以加网络吗_绿茶加蜂蜜的功效,绿茶可以加蜂蜜吗?

绿茶是我国的主要茶类之一&#xff0c;是一种天然健康的饮料&#xff0c;蜂蜜也是一种营养丰富的滋补食品&#xff0c;有些人不喜欢绿茶的苦味&#xff0c;想放点蜂蜜中和一下&#xff0c;但是不知道能不能这样做。那么绿茶能不能加蜂蜜呢?蜂蜜的主要成分是葡萄糖、果糖&#…

三分钟Docker-镜像、容器实战篇

本文主要内容&#xff1a;Docker 镜像、容器 常用命令整理使用Docker常见命令&#xff0c;搭建Consul集群通过创建自定义镜像&#xff0c;把.NetCore Api运行在Docker中1.镜像、容器命令镜像序号命令描述1docker image build基于Dockerfile创建镜像2docker image history显示镜…

手机键鼠映射软件_吃鸡,我最专业!---盖世小鸡键鼠吃鸡套装评测

Hello大家好&#xff0c;欢迎浏览这篇评测贴。首先很荣幸能够参与本期的评测&#xff0c;毕竟如此炫酷富有科技感的装备是可遇而不可求的&#xff0c;所以不论是得知入选还是收到快递开箱的时候&#xff0c;心情都是无比激动。话不多说&#xff0c;接下来就让我带你走进这个不一…

[Redis6]Redis启动_前台启动和后台启动

前台启动(不推荐) 前台启动&#xff0c;命令行窗口不能关闭&#xff0c;否则服务器停止 redis-server 关闭redis ctrlC : 关闭 后台启动&#xff08;推荐&#xff09; 备份redis.conf cd redis-6.2.6/cp redis.conf /etc/redis.confcd /etc后台启动设置daemonize no改成y…

深入剖析.NETCORE中CORS(跨站资源共享)

前言由于现代互联网的飞速发展&#xff0c;我们在开发现代 Web 应用程序中&#xff0c;经常需要考虑多种类型的客户端访问服务的情况&#xff1b;而这种情况放在15年前几乎是不可想象的&#xff0c;在那个时代&#xff0c;我们更多的是考虑怎么把网页快速友好的嵌套到服务代码中…

ai进入轮廓模式怎么退出_详解AI中扩展、扩展外观、轮廓化描边、创建轮廓

详解AI中扩展、扩展外观、轮廓化描边、创建轮廓在学习AI软件中&#xff0c;有不少同学分不清扩展、扩展外观、轮廓化描边、创建轮廓这四个概念具体的功能区别&#xff0c;今天我们具体聊一下。先说“扩展”&#xff0c;扩展是把复杂物体拆分成最基本的路径。矢量物体在组合&…

[Redis6]Redis相关知识介绍

Redis介绍相关知识 端口6379 6379 是 "MERZ " 九宫格输入法对应的数字。Alessia Merz 是一位意大利舞女、女演员。 Redis 作者 Antirez 早年看电视节目&#xff0c;觉得 Merz 在节目中的一些话愚蠢可笑&#xff0c;Antirez 喜欢造“梗”用于平时和朋友们交流&#x…