Natasha 高级编译类 - 第一部分
Posted 摧残一生 涅槃重生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Natasha 高级编译类 - 第一部分相关的知识,希望对你有一定的参考价值。
模板类的使用,类似于Lambda
类名 | 作用 | 命名空间 | 操作类型 |
---|---|---|---|
NAssembly | 快速创建同程序集的 oop 及委托等操作类 | 全局 | 静态初始化,动态实例化 |
NInstance | 根据类型,提供一个初始化实例的委托 | 全局 | 静态 |
NDelegate | 快速创建指定域的 Action/Func 委托 | 全局 | 静态初始化,动态实例化 |
NClass | 快速创建一个公有类 | 全局 | 静态初始化,动态实例化 |
NInterface | 快速创建一个公有接口 | 全局 | 静态初始化,动态实例化 |
NEnum | 快速创建一个枚举类 | 全局 | 静态初始化,动态实例化 |
NRecord | 快速创建一个记录类 | 全局 | 静态初始化,动态实例化 |
NStruct | 快速创建一个结构体 | 全局 | 静态初始化,动态实例化 |
FakeMethodOperator | 仿造 MethodInfo 创建方法 | Natasha.CSharp | 静态初始化,动态实例化 |
FastMethodOperator | 快速创建方法 | Natasha.CSharp | 静态初始化,动态实例化 |
NClass
感觉该类的使用频率会比较高
注意:NClass可以通过获得Method后在进行方法调用,或者实例化以后
使用自带方法进行创建
NatashaManagement.Preheating();
using (NatashaManagement.CreateDomain("Test").CreateScope())
// 创建class
NClass builder = NClass.UseScope();
var type = builder
// 不包含全局using
.NoGlobalUsing()
// 隐藏命名空间
.HiddenNamespace()
// 类的访问权限
.Access(AccessFlags.Public)
// 名称
.Name("Demo5")
// 带参构造函数
.Ctor(item => item.Public().Param<int>("test").Body("int _test = test;"))
// 属性
.Field(item => item.Public().Name("Age").Type<int>(); )
// 属性
.Field(item => item.Public().Name("Name").Type<string>(); )
// 封装的方法
.Property(item => item.Public().Name("Obj").Type<NClass>(); )
.GetType();
var script = builder.AssemblyBuilder.SyntaxTrees[0].ToString();
System.Console.WriteLine(script);
运行结果
另外附上一个较为全面的例子
//构建二 使用了上面例子的type
//添加了该引用一直无效果,因此直接将TestAttribute放到了代码中
NatashaManagement.AddGlobalReference(typeof(TestAttribute));
NClass builder2 = NClass.UseScope();
var type2 = builder2
.Public()
// 类名称
.Name("Demo51")
// 注释
.Summary("This is a test class;")
// 添加只读的int变量ReadonlyField
.PublicReadonlyField<int>("ReadonlyField")
// 声明一个构造函数
.Ctor(item => item.Public().Body("ReadonlyField = 10;"))
// 私有变量声明
.PrivateField<string>("_name", "[TestAttribute]")
// 声明了TestAttribute属性的Get方法
.Property(item => item
.Public()
.Attribute<TestAttribute>()
.Type<string>()
.Name("NameProperty")
.OnlyGetter("return _name;"))
// Get/Set方法
.Property(item => item
.Public()
.Type("AnotherClass")
.Name("AnotherProperty"))
// 名为SetName,参数为string的返回值为_name的虚方法
.Method(item => item
.Public()
.Virtrual()
.Async()
.Name("SetName")
.Param<string>("name")
.Body(@"_name = name;
return _name;")
.Return<Task<string>>())
// 在命名空间中额外添加一个AnotherClass方法
.NamespaceBodyAppend("public class AnotherClass")
.NamespaceBodyAppend("public class TestAttribute : Attribute ")
.GetType();
var script2 = builder2.AssemblyBuilder.SyntaxTrees[0].ToString();
// 打印
System.Console.WriteLine(script2);
运行结果
NEnum
枚举类
//没啥好说的。。。。
NEnum builder = NEnum.DefaultDomain();
var type = builder
.NoGlobalUsing()
.HiddenNamespace()
.Access(AccessFlags.Public)
.Name("EnumDemo")
.EnumField("Apple", 1, "苹果")
.EnumField("Orange", 2)
.EnumField("Banana", 4)
.GetType();
System.Console.Write(builder.AssemblyBuilder.SyntaxTrees[0].ToString());
运行结果
未完待续。。。
Natasha V1.3.6.0 的升级日志
开源库满足于个人,而完善于大众。
Natasha 自稳定版发布之后,众多老铁参与增强改进,感谢如下老铁的反馈:
1. 异常搜集
在 wenjq0911 建议下,添加了异常捕获,现 Natasha 的编译器已支持 Exception 字段,它将在整个编译周期中搜集异常。
var fastBuilder = FastMethodOperator.New;
fastBuilder.Complier.Exception; //编译后异常会进入这里
var fakeBuilder = FakeMethodOpeartor.New;
fakeBuilder.Complier.Exception;
var oopBuilder = new OopOperator();
oopBuilder.Complier.Exception;
if(Builder.Complier.Exception.ErrorFlag == ComplieError.None)
//编译成功!
UT地址:https://github.com/dotnetcore/Natasha/blob/master/test/NatashaUT/ExceptionTest.cs
2. Web环境
另外 wenjq0911 提供了 web 环境的运行信息,根据排查和调研,Natasha 现采用 AspNetCore 的 refs 子文件夹方式提供 web 应用程序的引用,配置文件内容已在 ReadMe 中更改。
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
// 一定要加上这句话
<PreserveCompilationContext>true</PreserveCompilationContext>
// WEB发布加
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish>
</PropertyGroup>
3. 异步方法
在 Jello 的建议下,增加了异步方法的反解还原,并在 FastMethodOperator 中支持 UseAsync/AsyncFrom 等异步来源方法。
public static async void RunAsyncDelegate2()
var delegateAction = FastMethodOperator.New
.UseAsync()
.Param<string>("str1")
.Param<string>("str2")
.MethodBody(@"
await Task.Delay(1000);
string result = str1 +"" ""+ str2;
Console.WriteLine(result);
return result;"
.Return<Task<string>>()
.Complie();
string result = await ((Func<string, string, Task<string>>)delegateAction)?.Invoke("Hello", "World1!");
Assert.Equal("Hello World1!", result);
UT地址:https://github.com/dotnetcore/Natasha/blob/master/test/NatashaUT/AsyncMethoddTest.cs
4. 智能方法
Wayne 和 Dennis 在异步的基础上给出了体验优化的建议,Natasha 的Complier
在不指定参数的情况下默认使用 TDelegate 的参数;
在不指定返回值的情况下,默认使用 TDelegate 的返回类型;
var delegateAction = FastMethodOperator.New
.UseAsync()
.MethodBody(@"
string result = arg1 +"" ""+ arg2;
Console.WriteLine(result);
return result;")
.Complie<Func<string, string, Task<string>>>();
string result =await delegateAction?.Invoke("Hello", "World2!");
Assert.Equal("Hello World2!", result);
UT地址:https://github.com/dotnetcore/Natasha/blob/master/test/NatashaUT/AsyncMethoddTest.cs
5. 外部文件与运行时脚本混合编译
在 Teng 的建议下,增加了外部文件和运行时脚本混合编译的功能。使用 LoadFile方法将外部 Dll 文件引入运行时,并添加到编译列表中。LoadFile 方法是在IComplier 抽象编译器中实现的,所以,只要 Builder 类实现了编译器,都将拥有此方法。
using System;
namespace ClassLibrary1
public class Class1
public void Show1()
Console.WriteLine("RunShow1");
public static void Show2()
Console.WriteLine("RunShow2");
string text = @"
using System;
using System.Text;
using ClassLibrary1;
namespace HelloWorld
public class Test
public override string ToString()
Class1 a = new Class1();
a.Show1();
Class1.Show2();
return ""11"";
";
//Class1 来自于 ClassLibrary1.dll
OopComplier oop = new OopComplier(); //OopComplier在2.0中移除
oop.LoadFile(@"D:\Project\IlTest\ClassLibrary1\bin\Debug\netstandard2.0\ClassLibrary1.dll");
Type type = oop.GetClassType(text);
//调用
var a = Activator.CreateInstance(type);
Console.WriteLine(a.ToString());
(2.0版本引擎升级后会将此方法包装进程序集域的操作类中)
6. 继承、重写与实现
allmyfantasy 建议下,完善了类、接口、抽象类、虚方法的实现。
ProxyOperator<Interface> builder = new ProxyOperator<Interface>();
builder.OopName("InterfaceClass");
builder["InterfaceMethod"] = "return 123456;"; // public method
builder.Compile();
var test = builder.Create("InterfaceClass");
ProxyOperator<Class> builder = new ProxyOperator<Class>();
builder.OopName("TestClass");
builder["NormalMethod"] = "return 123456;"; //new method
builder["VirtualMethod"] = "return 123456;"; //override method
builder.Compile();
dynamic test = Activator.CreateInstance(builder.TargetType);
ProxyOperator<Abstract> builder = new ProxyOperator<Abstract>();
builder.OopName("AbstractClass");
builder["AbstractMethod"] = "return 123456;"; //overrider method
builder.Compile();
var test = builder.Create("AbstractClass");
UT地址:https://github.com/dotnetcore/Natasha/blob/master/test/NatashaUT/ProxyTest.cs
7. 添加包装类
guodf、Teng、WeihanLi 的建议下,添加包装类提升使用体验。
var result = NewClass.Create(Action<OopOperator> action);
var result = NewInterface.Create(Action<OopOperator> action);
var result = NewStruct.Create(Action<OopOperator> action);
var type = result.Type;
var error = result.Exception;
var result = NewMethod.Create(Action<FastMethodOperator> action);
var error = result.Exception;
var method = result.Method;
method();
8. 支持非安全方法
根据 FUTURE* 的需求,支持了非安全方法的编译,现可以使用 UseUnsafe 方法来实现。
9. 快速实现动态功能
增加了 NFunc/NAction 两种快速实现委托的操作类。
//NFunc 和 NAction 支持的方法:
// 普通方法:Delegate
// 异步方法:AsyncDelegate
// 非安全方法:UnsafeDelegate
// 非安全异步方法:UnsafeAsyncDelegate
var action = NFunc<string, string, Task<string>>.UnsafeAsyncDelegate(@"
string result = arg1 +"" ""+ arg2;
Console.WriteLine(result);
return result;");
string result = await action("Hello", "World1!");
//result = "Hello World1!"
10. 枚举类型构建与编译
var script = new OopOperator()
.HiddenNameSpace().ChangeToEnum()
.OopAccess(AccessTypes.Public).OopName("EnumUT1")
.EnumField("Apple")
.EnumField("Orange",2)
.EnumField("Banana")
.Builder().Script;
/* result:
public enum EnumUT1
Apple,
Orange=2,
Banana*/
(2.0版本将在此基础上增加封装类)
11. 日志加深一级
\netcoreapp2.2\log\2019\08月19日\17时39分
(2.0版本将进行优化和改动)
鸣谢贡献者:
感谢 WeihanLi 帮忙做了 CodeReview 的工作。
感谢 Teng 帮忙做了 WikiReview 的工作。
Natasha2.0 将兼容 Core3.0 版本,除升级优化引擎之外还将支持隔离编译与卸载功能。后续还会跟随合理需求进行升级维护, 感谢各位的支持和鼓励。
欢迎访问主页并扫码进入 Natasha 生态群:https://github.com/dotnetcore/Natasha
孵化组正在进行的项目:DeepClone/NMapper/NCaller
以上是关于Natasha 高级编译类 - 第一部分的主要内容,如果未能解决你的问题,请参考以下文章