宁波网站建设公司在哪里,建设网站 安全事项,虚拟空间下载,asp建站系统源码背景#xff1a; IL编程在普通的程序员的代码里几乎不会出现#xff0c;但从Json.net、Dapper、Asp.net等等开源项目都体现出了IL编程的重要性。
在IL编程的时候#xff0c;上百行甚至上千行的IL代码实在让人头大#xff0c;调试不方便不说#xff0c;IL编程的逻辑也是不同… 背景 IL编程在普通的程序员的代码里几乎不会出现但从Json.net、Dapper、Asp.net等等开源项目都体现出了IL编程的重要性。
在IL编程的时候上百行甚至上千行的IL代码实在让人头大调试不方便不说IL编程的逻辑也是不同于以往的编程。
为了简化操作优化IL编程逻辑设计了这个库取名为Natasha. 简介 类库名称Natasha (娜塔莎)原型苏联红军第25步兵师的中尉柳德米拉·帕夫利琴科一名出色的女狙击手
开源协议MPL2.0
版 本2016
作 者LanX
感 谢Xue 和 Denni 在测试以及审查代码上的支持 地 址https://github.com/NMSLanX/Natasha 类库功能 动态方法支持多线程创建动态方法EMethod:对任意类方法的操作类EHandler:创建动态方法的操作类 普通变量EVar对int、double、bool、float、string…等变量的操作以及枚举类型的若干操作重载一元二元运算符提供各种变量(包括运行时)的 - * / % | –操作重载比较运算符提供各种变量(包括运行时)的比较操作;实现ILoadInstance数据入栈接口;临时变量可自加减以及Store赋值操作;可创建无临时变量的操作实例; 类和结构体EModel支持三种常规压栈方式(Builder,Action,Parameter);实现ILoadInstance数据入栈接口(this入栈);支持属性、字段、方法、私有属性字段结构体不支持的及时操作以及延迟操作;重载一元二元运算符提供各种变量(包括运行时)的 - * / % | 操作;重载比较运算符提供各种变量(包括运行时)的比较操作;支持链式加载或延迟加载嵌套类或结构体的属性、字段、方法;提供链式操作来操作方法返回来的对象且无临时变量;支持CreateModelFromObject方法进行深度压栈复制保证对象全新;提供EstruckCheck类检测结构体是否为刚初始化的结构体注结构体初始化不是空; 数组EArray支持三种常规压栈方式(Builder,Action,Parameter);实现ILoadInstance数据入栈接口(this入栈);提供StoreArray方法支持各种数据入栈填充数组;提供LoadArray函数加载指定索引出的元素入栈;支持CreateArrayFromRuntimeArray方法进行深度压栈复制保证对象全新直接等于也行; 条件分支EJudge提供了if elseif else三个函数对逻辑进行分支处理;提供了 TrueJump正确跳转函数FalseJump 错误跳转函数JumpTo无条件跳转函数;ENull提供了空值检测;EDefult提供了默认值检测;EDBNull提供了对DBNull类型检测; 循环结构ELoop提供了对数组的遍历操作;保留了对迭代器遍历的方法;提供了while循环操作; 拆装箱EPacketEPacket提供了装箱函数以及拆箱函数 自定义类ClassBuilder支持自定义类自定义属性字段方法及其保护级别等功能支持EModel使用自定义类 用前科普 动态方法IL环境: 我们创建动态方法时需要DynamicMethod对象创建ILGenerator实例来操作动态方法。 比如 ilA methodA.GetILGenerator(); ilB methodB.GetILGenerator(); 当你用ilA来写IL代码的时候不能用ilB来参与methodA的创建过程。 也就是ilA产生的临时变量不能用在ilB中ilA与ilB是相互隔离的。 我们在自定义类的时候也会有新的il产生在设置属性的get/set方法的时候也会有新的il产生。 这里还涉及到在动态方法中创建动态方法所以需要保证il的工作环境相对是隔离的。 因此设计了ThreadCache缓存类来设置和获取不同环境的IL或者action。 EVar提供了普通变量的操作 EClass提供了类和结构体的操作EArray提供了数组的操作这三个主要的操作类都有共同的基类ILGeneratorBase初始化时会从ThreadCache中取IL. 类的入栈过程 this.Age 1: this.Show() this指针入栈 在IL编程中 因此引出初始化类的几个初始化方法 private EModel(Type type, Action action): base(action, type){} private EModel(LocalBuilder builder, Type type): base(builder, type) {} private EModel(int parameterIndex, Type type): base(parameterIndex, type){} 不管上面三种你选择了哪一种this入栈都是由以下的接口来完成的。 还有ILoadInstance接口 void Load(); //不是结构体或者结构体作为值类型填充时入栈 void LoadAddress(); //如果是结构体得加载地址 注:实际封装要比这三种多详情请看工程里的例子 LocalBuilder是临时变量用Ldloc代码来调用;ParameterIndex指定参数索引用Ldarg等IL代码来调用;委托就是委托可能委托中的代码比前两种更复杂;委托形式外面的LocalBuilder参数形式将this入栈。调用show的methodinfo将this入栈。将1入栈。填充fieldinfo 或者 propertyinfo。 使用方法 创建动态方法: //动态创建Action委托
Delegate newMethod0 EHandler.CreateMethodENull((il){ }).Compile(); //动态创建Actionstring,int委托Delegate newMethod1 EHandler.CreateMethodstring,int,ENull((il){ }).Compile(); //动态创建Funcstring委托Delegate newMethod2 EHandler.CreateMethodstring((il) { }).Compile(); //动态创建Funcstring,TestClass委托Delegate newMethod3 EHandler.CreateMethodstring, TestClass((il) { }).Compile(); 创建普通变量(非结构体非类实例非数组): //动态创建Action委托
Delegate newMethod EHandler.CreateMethodENull((il) { //创建没有临时变量的普通入栈变量(没有临时变量所以自加操作没有意义) EVar intHandler 1; //创建函数操作句柄 EMethod method typeof(Console); //输出intHandler的时候让变量做加法运算。 method.ExecuteMethodint(WriteLine, intHandler 665); //结果:666 }).Compile();((Action)newMethod)(); //动态创建Action委托Delegate newMethod1 EHandler.CreateMethodENull((il) { //创建有临时变量的普通入栈变量(自加操作可以被自身储存) 也就是说可以使用store存储函数 //int i 664; EVar intHandler EVar.CreateVarFromObject(664); //i; intHandler; //ii1; intHandler.Store(intHandler 1); //创建函数操作句柄 EMethod method typeof(Console); //输出intHandler method.ExecuteMethodint(WriteLine, intHandler); //结果:666 }).Compile();((Action)newMethod1)(); 创建类\创建结构体: //动态创建Action委托
Delegate newMethod EHandler.CreateMethodENull((il) { EModel model null; //测试类的字段 //model EModel.CreateModelDocumentClassFieldTest(); //测试类的属性 //model EModel.CreateModelDocumentClassPropertyTest(); //测试结构体的字段 model EModel.CreateModelStructField(); //测试结构体的属性 // model EModel.CreateModelDocumentStructPropertyTest(); model.Set(PublicName, This is Public-Name); model.Set(PrivateName, This is Private-Name); model.Set(PublicAge, 666); model.Set(PrivateAge, 666); EMethod method typeof(Console); method.ExecuteMethodstring(WriteLine, model.Load(PrivateName)); method.ExecuteMethodstring(WriteLine, model.Load(PublicName)); method.ExecuteMethodint(WriteLine, model.Load(PublicAge)); method.ExecuteMethodint(WriteLine, model.Load(PrivateAge)); }).Compile();((Action)newMethod)(); 创建数组\遍历数组: string[] strArray new string[5];
StructField[] structArray new StructField[5];
DocumentEnum[] enumArray new DocumentEnum[5];for (int i 0; i strArray.Length; i 1)
{strArray[i] i.ToString();enumArray[i] DocumentEnum.ID;structArray[i] new StructField() { PublicAge i };
}//string数组遍历输出
Delegate newMethod EHandler.CreateMethodENull((il) { EMethod method typeof(Console); //从运行时获取数组并入栈到IL层临时变量 EArray stringArrayModel strArray; //遍历数组 ELoop.For(stringArrayModel, (currentElement) { method.ExecuteMethodstring(WriteLine, currentElement); }); }).Compile();((Action)newMethod)(); //自定义数组Delegate newMethod EHandler.CreateMethodENull((il) { //创建长度为10的int类型数组 EArray arrayModel EArray.CreateArraySpecifiedLengthint(10); //索引为56,7处填充数据6 arrayModel.StoreArray(5, 6); arrayModel.StoreArray(6, 6); arrayModel.StoreArray(7, 6); //遍历输出 ELoop.For(0, 10, 1, arrayModel, (currentElement) { method.ExecuteMethodint(WriteLine, currentElement); }); }).Compile();((Action)newMethod)(); //结构体数组遍历输出Delegate newMethod EHandler.CreateMethodENull((il) { //从运行时获取数组并入栈到IL层临时变量 或者EArray structArrayModel structArray EArray structArrayModel EArray.CreateArrayFromRuntimeArray(structArray); //遍历输出元素的PublicAge字段 ELoop.For(structArrayModel, (currentElement) { EModel model EModel.CreateModelFromAction(currentElement, typeof(StructField)); model.LField(PublicAge); method.ExecuteMethodint(WriteLine); }); }).Compile();((Action)newMethod)(); //结构体数组遍历输出Delegate newMethod EHandler.CreateMethodENull((il) { EArray enumArrayModel EArray.CreateArrayFromRuntimeArray(enumArray); ELoop.For(enumArrayModel, (currentElement) { //使用action方式来加载当前元素 EModel model EModel.CreateModelFromAction( currentElement, typeof(DocumentEnum) ); model.Load(); //加载之后装箱 EPacket.Packet(typeof(DocumentEnum)); //用object参数的方式输出 method.ExecuteMethodobject(WriteLine); }); }).Compile();((Action)newMethod)(); 条件: TestClass t new TestClass();t.Field 10;t.Property 20;Delegate showResult EHandler.CreateMethodENull((il) { EMethod method typeof(Console); EVar emit_A EVar.CreateWithoutTempVar(10); EVar emit_B EVar.CreateVarFromObject(20); EModel model EModel.CreateModelFromObject(t); EJudge.If(emit_A model.DLoad(Field).Model)(() { method.ExecuteMethodint(WriteLine, 10); }).ElseIf(emit_A emit_B)(() { method.ExecuteMethodint(WriteLine, emit_A); }).Else(() { method.ExecuteMethodint(WriteLine, emit_B); }); while循环: Delegate showResult EHandler.CreateMethodENull((il) { EMethod method typeof(Console); EVar emit_A EVar.CreateWithoutTempVar(16); EVar emit_B EVar.CreateVarFromObject(20); ELoop.While(emit_A emit_B)(() { method.ExecuteMethodint(WriteLine, emit_B); emit_B--; }); TestClass t new TestClass() { Field 10 }; EModel model EModel.CreateModelFromObject(t); ELoop.While(model.DLoad(Field).Model emit_B)(() { //Console.WriteLine(model.field); //这里需要传递委托不传递委托则返回的是model类型而不是int类型 method.ExecuteMethodint( WriteLine, model.DLoad(Field).DelayAction ); //model.Field model.DLoad(Field).Model; }); ELoop.While(model.DLoad(Field).Model ! 25)(() { method.ExecuteMethodint( WriteLine, model.DLoad(Property).DelayAction ); model.DLoad(Property).Model; }); }).Compile();((Action)showResult)(); 自定义类/使用自定义类: ClassBuilder builder ClassBuilder.CreateModel(Hello);
builder.CreateDefaultConstructor();
builder.CreateFieldstring(Age, FieldAttributes.Public);
builder.CreatePropertystring(Name);
builder.CreateMethodENull(Show, MethodAttributes.Public, (classModel) { classModel.SField(Age, This is Age.); classModel.SProperty(Name, This is name.); classModel.LPropertyValue(Name); classModel.ilHandler.Emit(OpCodes.Call, typeof(Console).GetMethod(WriteLine, new Type[] { typeof(string) })); classModel.ilHandler.Emit(OpCodes.Ret); //下一版酌情对Method创建做优化 });builder.EndBuilder(); //使用自定义类Delegate ShowDelegate EHandler.CreateMethodENull((il) { ClassHandler Model ClassHandler.CreateInstance(Hello); Model.EMethod(Show); Model.LField(Age); Model.ilHandler.Emit(OpCodes.Call, typeof(Console).GetMethod(WriteLine, new Type[] { typeof(string) })); }).Compile();((Action)ShowDelegate)(); 补充: 更多的详细用法请参照源代码中工程例子对于迭代接口请实现Iiterator接口并调用Eloop的Foreach方法进行遍历。 以下是List的迭代接口实现案例考虑在下一版中实现对迭代器的支持 迭代器实现: #region 迭代器属性和方法(不支持)public int Length
{ get; set;
}#endregion#region 迭代器属性和方法(支持)public LocalBuilder TempEnumerator
{ get; set;
}public MethodInfo MoveNext
{ get; set;
}public MethodInfo Current
{ get; set;
}public MethodInfo Dispose
{ get; set;
}public void LoadCurrentElement(LocalBuilder currentBuilder)
{ilHandler.Emit(OpCodes.Ldloca, TempEnumerator);ilHandler.Emit(OpCodes.Call, Current);
}public void Initialize()
{ if (TempEnumerator null){TempEnumerator ilHandler.DeclareLocal(typeof(ListT.Enumerator));MethodInfo GetEnumerator TypeHandler.GetMethod( GetEnumerator, new Type[0]);LoadAddress();ilHandler.Emit(OpCodes.Callvirt, GetEnumerator);ilHandler.Emit(OpCodes.Stloc, TempEnumerator);MoveNext typeof(ListT.Enumerator).GetMethod( MoveNext, new Type[0]);Current typeof(ListT.Enumerator).GetProperty(Current).GetGetMethod(true);Dispose typeof(ListT.Enumerator).GetMethod(Dispose, new Type[0]);}
}#endregio 愿景 1、希望大家以平和的心态去对待菜鸟开源库的事情
2、Json.net 不也是人写出来的吗Dapper是凭空产生的吗希望大家发挥自己的创造力共创辉煌 计划 1、本库采用MPL2.0开源协议、召集小伙伴继续完善下去欢迎加入到开发队伍中QQ群号573026640
2、Natasha每年更一次正式版版本号用去年的年号 吐槽 对于说我重复造轮子的人我没什么好说的谁造谁知道
对于说我装B的人我想说一下你猜错了我想装C装完C还想装D这个库2016年开始封装中间推翻了两版重构十次以上精神分裂、懵逼N次怀疑人生1次求小伙伴们一起参与到建设中来!为什么拿Natasha来命名这个库因为她墓志铭上有这两句话痛苦如此持久像蜗牛充满耐心地移动
快乐如此短暂像兔子的尾巴掠过秋天的草原跟开发过程相符 结尾 我相信这行没有学习能力是走不远的。
我也相信没有创造力是看不清未来的。 愿这个库能给您的项目带来方便给创作带来便利与灵感。 希望.NET在接下来的发展中能吸引更多的创造者让.NET世界百花齐放。 原文地址http://blog.csdn.net/lanx_fly/article/details/59617050 .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注