文章转载授权级别:C
Natasha 是一个代替 Emit / Expression 的动态构建项目,旨在为开发者提供方便、快捷、高性能的动态构建服务,动态编程是生态的重要组成部分,希望开发者们能有足够的兴趣来了解、使用、建设它。
1、插件生成
使用 Natasha 进行动态编译并生成 dll 和 pdb 文件;
//使用随机域
//参数传 true 将内容编译到 DLL 中
NDomain.Random(true).Action("Console.WriteLine(\"Hello World!\");");
2、插件加载
前提插件结构:
Plugin 引用了 Dependency.dll 和 MySql.Data.dll
.NET Core 2.x 使用 Natasha 加载插件,建议手动添加依赖。
var domain = DomainManagement.Random;
domain.LoadStream("Plugin.dll");
domain.LoadStream("Dependency.dll");
domain.LoadStream("MySql.Data.dll");NDomain.Create(domain).Action("xxxx");
.NET Core3.x 官方在 core3.x 后提供了 AssemblyDependencyResolver 操作类来解析 deps.json 依赖配置文件,因此不需要再一个一个的添加了。
AssemblyDependencyResolver 操作类仅对外提供两个解析路径的方法,若需要获取引用文件的路径,需要反射私有字段。
var domain = DomainManagement.Random;
domain.LoadStream("Plugin.dll");NDomain.Create(domain).Action("xxxx");
3、运行时动态修改插件
在群里小伙伴的建议下,开了一个动态修改插件的项目:https://github.com/night-moon-studio/DynamicPlugin ,结合 Natasha 出色的正编译及插件功能 和 ILSpy 超强的反编译功能,我们允许一个插件在运行时加载之后进行部分修改并重新编译。
场景:前提插件 Plugin 包含有 A \ B \ C 三个类, 需求是在不改变类 A \ B 的情况下,修改 C 的代码并重新生成插件,中间不能关闭程序。
//当插件使用deps.json依赖文件时
ReWriter reWriter = new ReWriter(dllPath);
reWriter["C"] = "using xxxx; namespace xxx{public class C{ ...... }}";
reWriter.Complier();
reWriter.Dispose();
return reWriter.NewDllPath;
//当插件不适用deps.json文件,且所有依赖文件都在同一目录时
ReWriter reWriter = new ReWriter(dllPath,false);
//添加额外引用DLL
reWriter.References.Add("MySql.Data.dll");
reWriter.References.Add("xxxx.dll");
reWriter["C"] = "using xxxx; namespace xxx{public class C{ ...... }}";
reWriter.Complier();
reWriter.Dispose();
return reWriter.NewDllPath;
Github 代码中的例子结果对比图:
对新旧 dll 反编译查看(下为新),可以发现 Natasha 在生成插件的同时对编译代码还进行了优化。
对其他类进行对比查看,虽然反编译里软件中显示了乱码,实际上在运行时得到的结果并没有乱码,得益于 ILSpy 对 dynamic 的反解。
4、结尾
不太会说废话,但唐突的结束不是很好,希望大家能多多吐槽我们的项目,多提建议,如果没什么问题就去干吧,干就完了.
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
长按左侧二维码关注
欢迎打赏组织
给予我们更多的支持