MSIL实用指南-加载null、string、long、float、double等值

本篇讲述怎么加载null、string值、long值、float值、double值。

加载null不需要参数值,只要

Emit ldnull

其它几个命令要

Emit <指令> <值>

加载null

加载null是很简单的,使用OpCodes.Ldnull,以下一句程序就可以了。

ilGenerator.Emit(OpCodes.Ldnull);

加载string

加载string值也很简单,使用OpCodes.Ldstr,格式是

ilGenerator.Emit(OpCodes.Ldstr, <string值>);

比如

ilGenerator.Emit(OpCodes.Ldstr, "hello...");

加载long

使用格式OpCodes.Ldc_I8指令,是ilGenerator.Emit(OpCodes.Ldc_I8, <long值>);

比如

ilGenerator.Emit(OpCodes.Ldc_I8, long.MaxValue);

需要注意的是,下面这一句是有问题的,120默认是int型,不是long型,生成的指令是没法正确运行的。

ilGenerator.Emit(OpCodes.Ldc_I8, 120);

必须加long强制转换,修正为

ilGenerator.Emit(OpCodes.Ldc_I8, (long)120);

加载float

使用格式OpCodes.Ldc_R4指令,格式是ilGenerator.Emit(OpCodes.Ldc_R4, <float值>);

比如

ilGenerator.Emit(OpCodes.Ldc_R4, float.MinValue)

也要注意的,下面这一句有问题,5.5默认是dobule型,不是float型,生成的指令也不能正确运行的。

ilGenerator.Emit(OpCodes.Ldc_R4, 5.5);

必须加long强制转换,修正为

ilGenerator.Emit(OpCodes.Ldc_R4, (float)5.5);

加载double

使用格式OpCodes.Ldc_R8指令,格式是ilGenerator.Emit(OpCodes.Ldc_R4, <double值>);

比如

ilGenerator.Emit(OpCodes.Ldc_R8, (double)6.5);

完整的程序如下:

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace LX1_ILDemo
{
    /// <summary>
    /// load null、string值、long值、float值、double值、
    /// </summary>
    class Demo02_LoadLFDSN
    {
        static string binaryName = "Demo02_LoadLFDSN.exe";
        static string namespaceName = "LX1_ILDemo";
        static string typeName = "LoadLFDSN";

        static AssemblyBuilder assemblyBuilder;
        static ModuleBuilder moduleBuilder;
        static TypeBuilder typeBuilder;
        static MethodBuilder mainMethod;
        static ILGenerator ilGenerator;

        static void Emit_Ldc()
        {
            /* 加载string值的Ldstr指令使用 */
            MethodInfo writeStringLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });

            /* 加载null的Ldnull指令使用 */
            ilGenerator.Emit(OpCodes.Ldnull);//ldnull
            ilGenerator.Emit(OpCodes.Call, writeStringLineMethod);

            /* 加载string的Ldstr指令使用 */
            ilGenerator.Emit(OpCodes.Ldstr, "hello...");//ldstr "hello..."
            ilGenerator.Emit(OpCodes.Call, writeStringLineMethod);

            /* 加载long值的Ldc_I8指令使用 */
            MethodInfo writeLongLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(long) });
            ilGenerator.Emit(OpCodes.Ldc_I8, (long)120);//数值前面的强制转换‘(long)’是必须的,默认会把‘120’作为int,导致生成的程序运行错误
            ilGenerator.Emit(OpCodes.Call, writeLongLineMethod);
            ilGenerator.Emit(OpCodes.Ldc_I8, long.MaxValue);//ldc.i8     0x7fffffffffffffff
            ilGenerator.Emit(OpCodes.Call, writeLongLineMethod);
            ilGenerator.Emit(OpCodes.Ldc_I8, long.MinValue);//ldc.i8     0x8000000000000000
            ilGenerator.Emit(OpCodes.Call, writeLongLineMethod);

            /* 加载float值的Ldc_R4指令使用 */
            MethodInfo writeFloatLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(float) });
            ilGenerator.Emit(OpCodes.Ldc_R4, (float)5.5);//数值前面的强制转换‘(float)’是必须的,默认会把‘5.5’作为double,导致生成的程序运行错误
            ilGenerator.Emit(OpCodes.Call, writeFloatLineMethod);
            ilGenerator.Emit(OpCodes.Ldc_R4, float.MaxValue);//ldc.r4     3.4028235e+038
            ilGenerator.Emit(OpCodes.Call, writeFloatLineMethod);
            ilGenerator.Emit(OpCodes.Ldc_R4, float.MinValue);//ldc.r4     -3.4028235e+038
            ilGenerator.Emit(OpCodes.Call, writeFloatLineMethod);

            /* 加载double值的Ldc_R8指令使用 */
            MethodInfo writeDoubleLineMethod = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(double) });
            ilGenerator.Emit(OpCodes.Ldc_R8, (double)6.5);//ldc.r8     6.5
            ilGenerator.Emit(OpCodes.Call, writeDoubleLineMethod);
            ilGenerator.Emit(OpCodes.Ldc_R8, double.MaxValue);//ldc.r8     1.7976931348623157e+308
            ilGenerator.Emit(OpCodes.Call, writeDoubleLineMethod);
            ilGenerator.Emit(OpCodes.Ldc_R8, double.MinValue);//ldc.r8     -1.7976931348623157e+308
            ilGenerator.Emit(OpCodes.Call, writeDoubleLineMethod);
        }

        public static void Generate()
        {
            InitAssembly();

            /* 生成 public class LoadLFDSN */
            typeBuilder = moduleBuilder.DefineType( namespaceName+"."+ typeName, TypeAttributes.Public);

            /* 生成 public static void Main() */
            GenerateMain();

            Emit_Ldc();

            EmitReadKey();
            ilGenerator.Emit(OpCodes.Ret);

            /*  设置assembly入口方法 */
            assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);

            SaveAssembly();
            Console.WriteLine("生成成功");
            //Console.ReadKey();
        }

        static void EmitReadKey()
        {
            /* 生成 Console.ReadKey(); */
            MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
            ilGenerator.Emit(OpCodes.Call, readKeyMethod);
            ilGenerator.Emit(OpCodes.Pop);
        }

        static void GenerateMain()
        {
            mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(void), new Type[] { });
            ilGenerator = mainMethod.GetILGenerator();
        }

        static void InitAssembly()
        {
            AssemblyName assemblyName = new AssemblyName(namespaceName);
            assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
            moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, binaryName);
        }

        static void SaveAssembly()
        {
            Type t = typeBuilder.CreateType(); //完成Type,这是必须的
            assemblyBuilder.Save(binaryName);
        }
    }
}

原文地址:https://www.cnblogs.com/tkt2016/p/8573502.html

时间: 2024-11-08 19:01:08

MSIL实用指南-加载null、string、long、float、double等值的相关文章

MSIL实用指南-字段的加载和保存

字段有静态字段和非静态字段之分,它们的加载保存指令也是不一样的,并且非静态字段要生成this. 静态字段的加载加载静态字段的指令是Ldsfld.ilGenerator.Emit(OpCodes.Ldsfld, <FieldBuilder>);实际例子 ilGenerator.Emit(OpCodes.Ldsfld, areaFieldBuilder); ilGenerator.Emit(OpCodes.Call, writeStringLineMethod); 静态字段的保存保存静态字段的指令

MSIL实用指南-生成属性

本篇讲解怎么生成属性,包括get和set方法. 第一步,生成一个字段生成字段用TypeBuilder.DefineField方法.实例代码: FieldBuilder customerNameBldr = typeBuilder.DefineField ("_CustomerName",typeof(string),FieldAttributes.Private); 第二步,创建一个PropertyBuilder对象创建PropertyBuilder对象需要用生成字段用方法TypeBu

MSIL实用指南-闭包的生成和调用

闭包(Closure)是词法闭包(Lexical Closure)的简称.对闭包的具体定义有很多种说法,这些说法大体可以分为两类: 一种说法认为闭包是符合一定条件的函数,比如参考资源中这样定义闭包:闭包是在其词法上下文中引用了自由变量(注1)的函数.另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体.比如参考资源中就有这样的的定义:在实现深约束(注2)时,需要创建一个能显式表示引用环境的东西,并将它与相关的子程序捆绑在一起,这样捆绑起来的整体被称为闭包.这两种定义在某种意义上是对立的,

MSIL实用指南-类相关生成

一.创建class用MethodBuilder的DefineType方法,可以指定父类,得到一个TypeBuilder对象. 二.实现继承接口用TypeBuilder的AddInterfaceImplementation方法. 三.显示方法重写用TypeBuilder的DefineMethodOverride方法. 完整代码如下: using System; using System.Reflection; using System.Reflection.Emit; namespace LX1_

MSIL实用指南-生成for语句

for语句格式是这样的for(<初始化语句>;<条件语句>;<自增减语句>) <循环体> 它可以转换为while语句 if(<条件语句>){ <初始化语句> while(<条件语句>) { <循环体> <自增减语句> }} 那么就可以按照这while语句生成. 原文地址:https://www.cnblogs.com/tkt2016/p/8807388.html

MSIL实用指南-数据类型转换

一.类的强制转换1.转换成某个类用Castclass指令.实例代码:ilGenerator.Emit( OpCodes.Castclass , typeof(ClassA) ); 2.转换成某个值类型用Unbox_Any指令.实例代码:ilGenerator.Emit( OpCodes.Unbox_Any , typeof(DateTime) );ilGenerator.Emit( OpCodes.Unbox_Any , typeof(int) ); 二.值类型的强制转换 1.转化为sbyte用

Day1 (let and var)/(String,Int,Float,Double)/(Tuples,contains: array,dictionary)

let secondSystem:Int = 0b10001 let eightSystem:Int  = 0o21 let tenSystem:Int    = 17 let sixthSystem:Int  = 0x11 // summary: 1.u need insert a "Enter" behind equal symbol let num_a:Float = 1 let num_b:Int = 1 let a:Int = 3 let b:Double = 0.14159

安卓图片加载框架--Universal-Image-Loader

今天来介绍图片加载的框架Android-Universal-Image-Loader GITHUB上的下载路径为:https://github.com/nostra13/Android-Universal-Image-Loader 也可以自行百度下载. 首先来封装的一个类CacheTool ,由于其他加载图片的方法有点繁琐,所以这里仅封装了一个简单实用的加载方法: import android.graphics.Bitmap; import android.widget.ImageView; i

Web前台直接加载GIS格式数据分析

本文以Flex直接加载Shp.DWG和MDB为例. 首先看一份现估测数据: 1)  加载Shp文件,目前直接由前台Flex代码完成: 图1 在ArcCatalog里面的Shp文件 图2 直接在前台加载后的Shp文件 结果显示: Shp文件 大小 加载时间 Shp1 50kb 约3s Shp2 750kb 约10s 分析:未用后台开发,直接使用前台Flex对SHP开放数据加载,省去通讯时间,速度快捷,速度与客户端配置成正比. 说明:直接加载使用了LibertyGIS.swc组件. 2)  加载Dw