最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

世界快播:Natasha入门(一)

来源:博客园

什么是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}");
  • 执行结果结果如下

关键词: