资讯 更多 >>
国内油价将迎来下调:国际原油跌破9...
国家能源局:今年以来我国煤炭生产...
河南4名阳性人员私自返乡并瞒报情况...
山西吕梁:发现盗采矿产资源行为可举报
受害方律师:接法院通知,乐安命案...
橙色——“柑橘院士”邓秀新心中最...
刷视频相认的双胞胎姐妹:两次创业...
四川通报2021年秋冬季首批大气污染...
首轮筛查:天津73443人全部阴性!
首席气象预报员张霞:30年坚守筑牢...
动态更多 >>
你们,温暖了2021
西安市新增27个中风险地区 目前有1...
广西新增本土确诊病例1例
哈尔滨市全域均为低风险地区
寒潮将影响我国中东部地区 四川盆...
昆明至哈尔滨一航班发现1名入境复阳...
陕西研考:封控区内考生在原报考点...
北京今日最高气温仅5℃ 明起强冷空...
那年今日 | 历史上的12月22日发生...
我要找债主
会展 更多 >>
美籍酿酒师在崇礼:中国是第二故乡...
河南项城报告2名疑似新冠肺炎病例 ...
浙江绍兴确诊病例首次零新增 上虞...
广西东兴实行全员居家隔离 启动口...
新疆全方位推进乡村振兴 “富春山...
云南瑞丽市主城区全员核酸检测结果...
内蒙古满洲里累计治愈出院本土确诊...
孙海洋夫妻驱车山东阳谷:还在为孙...
大国工匠追梦“玉米强国”40载:用...
让南海“海洋热带雨林”斑斓多彩
专题报道 
当前位置: 关注 > >> 正文
 
每日关注!Natasha入门(一)
来源:博客园     时间:2023-04-13 16:58:15

什么是Natasha

Natasha是基于Roslyn 的动态程序构架库,说的直白一点就是将一个或多个cs文件进行动态编译并放入到正在运行的程序中去。例如我们有一个设备库,设备库中的设备会不定期的更新,那我们只需要将平台(展示和调用)完成,每次添加的时候使用Natasha生成设备类别和设备的调用代码,由平台统一调用。这样子就避免了每次调用都要重新生成和更新,每个设备模块都是单独的个体,个体出现bug不影响整个平台的正常工作。


(相关资料图)

Natasha使用场景

  • 插件管理,开发一个平台,里面有各式各样的插件,插件可通过引用等方式动态添加
  • 在线编码平台,在页面中输入代码,系统根据代码自动生成结果并展示
  • 代码生成器,通过编写Entity或读取数据源中的数据来生成代码块,并通过Natasha动态编译到系统中
  • 低代码平台

Natasha简单例子

  • 下载最新版 Natasha源码 ,目前最新版本为v5.1.0.0

  • 打开下载好的源码,编译src->CSharp->Natasha.CSharp项目,会生成如下两个dll

    • Natasha.CSharp.dll
    • Natasha.Domain.dll
  • 创建一个空项目NatashaStudyApplication,然后再创建一个控制台项目NatashaStudyConsole,框架选择了.Net7。

  • 需要额外使用NuGet添加三个引用

    • 添加引用Microsoft.Extensions.DependencyModel,否则初始化时(NatashaInitializer.Preheating方法)会报错。

    • 添加引用Microsoft.CodeAnalysis.CSharp,否则创建编译单元时会报错。

    • 如果使用官网给出的例子,oop.Add方法会提示错误,需要额外安装Microsoft.CodeAnalysis.Common包。

  • 在NatashaStudyConsols项目中创建dlls文件夹,将生成的Natasha.CSharp.dll和Natasha.Domain.dll都赋值到dlls文件夹中,为了防止丢失文件,我全部复制过来了

  • 选择依赖项,点击右键添加项目引用,选择浏览,找到本项目的dlls文件夹,然后把两个dll都进行引入,引入后如图所示:

  • 向Program中的Main中添加代码,官方给出的为声明一个class类,在使用该类时发现回报如下错误:

    Predefined type "System.Object" is notdefinedorimported

    "object" does notcontain a constructor that takes 0 arguments

    该错误的意思是程序没有声明System.Object

    • 方案一:基于Microsoft.Extensions.DependencyModel包,在PropertyGroup标签中添加true

    • 方案二:添加System.Object(System.Runtime.dll),找到System.Runtime.dll,然后对其进行引用MetadataReference.CreateFromFile("/dlls/System.Runtime.dll")

  • 本次的例子是基于官网的进行了补充

    //得到的结果string result = "";//初始化 Natasha 编译组件及环境NatashaInitializer.Preheating();//创建编译单元,并指定程序集名AssemblyCSharpBuilder oop = new AssemblyCSharpBuilder("myAssembly");//编译单元使用从域管理分配出来的随机域oop.Domain = DomainManagement.Random();//增加代码到编译单元中oop.Add(@"namespace HelloWorld{          public class Test{             public Test(){ Name = null; }            public string Name;             public void setName(string name){Name=name;}            public string getName(){                return ""你好!""+ Name;            }    }  }");//获得Assemblyvar assembly = oop.GetAssembly();// 利用反射实例化var newInstance = assembly.CreateInstance("HelloWorld.Test");//判断实例化是否成功if (newInstance != null) {    //获得setName方法    MethodInfo? setNamehod = newInstance.GetType().GetMethod("setName");    if (setNamehod != null) {        //利用反射进行赋值        setNamehod.Invoke(newInstance, new object[] { "张三" });    }    //获得getName方法    MethodInfo? getNameMethod = newInstance.GetType().GetMethod("getName");    if (getNameMethod != null)    {        // 获得getName的返回值        result = getNameMethod.Invoke(newInstance, null) as string;    }}//打印Console.WriteLine($"{result}");
  • 执行结果结果如下

  • 第二个例子使用官方例子

    //在 NDomain1 域内创建一个委托var func = NDelegate.CreateDomain("NDomain1").Func("return \"Hello World!\";");result = func();func.DisposeDomain();//打印Console.WriteLine($"{result}");
  • 执行结果结果如下

关键词:

热门推荐
猜你喜欢