• MSIL实用指南-Action的生成和调用


    MSIL实用指南-Action的生成和调用

    System.Action用于封装一个没有参数没有返回值的方法。这里生成需要Ldftn指令。

    下面讲解怎生成如下的程序。

    class ActionTest
        {
            public static void RunAction(Action act)
            {
                act();
            }
    
            public static void TestRunAction()
            {
                Action act = () => { Console.WriteLine("Test Action"); };
                RunAction(act);
            }
        }

    一.Action的调用
    Action有方法Invoke,只要加载对象,调用Invoke方法就可以了。
    实例代码:

    ilGenerator.Emit(OpCodes.Ldarg_0);
    ilGenerator.Emit(OpCodes.Callvirt, typeof(Action).GetMethod("Invoke", new Type[] { }));

    二、生成Lamda表示式
    这里的Lamda表示式即一个匿名方法,它只有一条语句。
    所以这样生成:

    lambdaMethod = typeBuilder.DefineMethod("<LambdaMethod>",
    MethodAttributes.Private| MethodAttributes.Static,
    typeof(void), new Type[] { });
    ILGenerator ilGenerator = lambdaMethod.GetILGenerator();
    ilGenerator.EmitWriteLine("Test Action");
    ilGenerator.Emit(OpCodes.Ret);

    三、生成Action实例
    Action是委托,它需要使用Ldftn和Newobj指令生成实例
    实例代码

    ilGenerator.Emit(OpCodes.Ldnull);//静态方法加载null,实例方法加载arg_0
    ilGenerator.Emit(OpCodes.Ldftn, lambdaMethod);
    ilGenerator.Emit(OpCodes.Newobj, typeof(Action).GetConstructors()[0]);

    完整程序:

    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace LX1_ILDemo
    {
        class Demo28_Action
        {
            static string binaryName = "Demo28_Action.exe";
            static string namespaceName = "LX1_ILDemo";
            static string typeName = "Demo28";
    
            static AssemblyBuilder assemblyBuilder;
            static ModuleBuilder moduleBuilder;
            static TypeBuilder typeBuilder;
            static MethodBuilder mainMethod;
            static MethodBuilder runActionMethod;
            static MethodBuilder lambdaMethod;
    
            static void Emit_TestMethod()
            {
                runActionMethod = typeBuilder.DefineMethod("RunAction", MethodAttributes.Public
                   | MethodAttributes.Static, typeof(void), new Type[] { typeof(Action) });
                ILGenerator ilGenerator = runActionMethod.GetILGenerator();
                ilGenerator.Emit(OpCodes.Ldarg_0);
                ilGenerator.Emit(OpCodes.Callvirt, typeof(Action).GetMethod("Invoke", new Type[] { }));
                ilGenerator.Emit(OpCodes.Ret);
            }
    
            public static void Generate()
            {
                InitAssembly();
                typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName, TypeAttributes.Public);
    
                Emit_TestMethod();
                GenerateMain();
    
                assemblyBuilder.SetEntryPoint(mainMethod, PEFileKinds.ConsoleApplication);
                SaveAssembly();
                Console.WriteLine("生成成功");
            }
    
            static void GenerateLambda()
            {
                lambdaMethod = typeBuilder.DefineMethod("<LambdaMethod>",
                    MethodAttributes.Private| MethodAttributes.Static,
                    typeof(void), new Type[] { });
                ILGenerator ilGenerator = lambdaMethod.GetILGenerator();
                ilGenerator.EmitWriteLine("Test Action");
                ilGenerator.Emit(OpCodes.Ret);
            }
    
            static void GenerateMain()
            {
                mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public
                    | MethodAttributes.Static, typeof(void), new Type[] { });
                ILGenerator ilGenerator = mainMethod.GetILGenerator();
    
                LocalBuilder localBuilderv1 = ilGenerator.DeclareLocal(typeof(Action));
    
                GenerateLambda();
                ilGenerator.Emit(OpCodes.Ldnull);//静态方法加载null,实例方法加载arg_0
                ilGenerator.Emit(OpCodes.Ldftn, lambdaMethod);
                ilGenerator.Emit(OpCodes.Newobj, typeof(Action).GetConstructors()[0]);
                ilGenerator.Emit(OpCodes.Stloc_0);
    
                ilGenerator.Emit(OpCodes.Ldloc_0);
                ilGenerator.Emit(OpCodes.Call, runActionMethod);
    
                EmitReadKey(ilGenerator);
    
                ilGenerator.Emit(OpCodes.Ret);
            }
    
            static void EmitReadKey(ILGenerator ilGenerator)
            {
                MethodInfo readKeyMethod = typeof(Console).GetMethod("ReadKey", new Type[] { });
                ilGenerator.Emit(OpCodes.Call, readKeyMethod);
                ilGenerator.Emit(OpCodes.Pop);
            }
    
            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);
            }
        }
    }
    View Code
  • 相关阅读:
    银联支付集成之 ---- 安卓
    在Mac系统下配置PHP运行环境
    ios工程中一天只让显示一次的广告,或是弹出窗,如何实现
    iOS工程中一天只让进行一次的操作如何做?
    简单实现UIlabel可复制功能
    iOS添加测试设备与调试
    iOS-最全的App上架教程
    javaIO--文件操作类
    javaIO--字符流
    javaIO--字节流
  • 原文地址:https://www.cnblogs.com/tkt2016/p/8865761.html
Copyright © 2020-2023  润新知