• MSIL实用指南-创建方法和定义参数


     本篇讲解实现创建方法、指定参数的名称、实现参数加out和ref修饰符、以及参数加默认值。

    创建方法

    创建方法用类TypeAttributes的

    DefineMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)

    方法,返回结果是MethodBuilder,就可以创普通方法。

    例子

    MethodBuilder m2 = typeBuilder.DefineMethod("M2",
    MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
    typeof(string), new Type[] { typeof(int), typeof(string), typeof(object) });

    这个写法就和下面的C#程序一样

    public abstract void M1();

    定义一个抽象方法需要用MethodAttributes的Abstract|Virtual才可以。

    定义参数

    用MethodBuilder的DefineParameter(int position, ParameterAttributes attributes, string strParamName)

    方法

     参数说明

    position:该参数在参数列表中的位置。为参数编索引,第一个参数从数字 1 开始;数字 0 表示方法的返回值。

    attributes: 参数的参数属性。

    strParamName: 参数名。名称可以为 null 字符串。

    返回结果:

    返回一个 ParameterBuilder 对象,该对象表示此方法的参数或此方法的返回值。

    1.指定参数的名称

    在程序的方法调用中传入第三个参数传入参数名称就可以了。

    例如

    MethodBuilder m2 = typeBuilder.DefineMethod("M2",
                   MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                   typeof(string), new Type[] { typeof(int), typeof(string), typeof(object) });
    
    m2.DefineParameter(1, ParameterAttributes.None, "arg0");
    m2.DefineParameter(2, ParameterAttributes.None, "param1");
    m2.DefineParameter(3, ParameterAttributes.None, "param2");

    这个方法的三个参数名称依次是arg0、param1、param2。

    2.指定参数out

    我们要实现如下方法,参数的修饰符是out

    public abstract string mout(out int arg3 );

    需要使用ParameterAttributes.Out就可以了。

    具体实现

    MethodBuilder m5 = typeBuilder.DefineMethod("mout",
                   MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                   typeof(string), new Type[] { typeof(int), typeof(int) });
    
                ParameterBuilder m5p1 = m5.DefineParameter(1, ParameterAttributes.Out, "arg3");
    

    3.实现参数默认值

    要实现参数有默认值,比如下面这句

    public abstract string mdefault(int arg1 =4 );

    实现这个效果的程序是

    MethodBuilder m3 = typeBuilder.DefineMethod("mdefault",
                   MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                   typeof(string), new Type[] { typeof(int) });
    
                ParameterBuilder m3p1 = m3.DefineParameter(1, ParameterAttributes.HasDefault | ParameterAttributes.Optional, "arg1");
                m3p1.SetConstant(4);

    实现定义参数属性为ParameterAttributes.HasDefault | ParameterAttributes.Optional,并得到一个

    ParameterBuilder实例,再设置这个实例的默认值。

    4.实现指定参数ref

    我们要实现如下方法,参数的修饰符是out

    public abstract string mref(ref dobule arg2);

    首先

    MethodBuilder m4 = typeBuilder.DefineMethod("mref",
                   MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                   typeof(string), new Type[] { Type.GetType("System.Double&") });

    参数的类型不是一般的typeof(double),而要用特殊的Type.GetType("System.Double&")

    其次

    ParameterBuilder m4p1 = m4.DefineParameter(1, ParameterAttributes.Out, "arg2");

    要设置参数的属性为ParameterAttributes.Out

    完整程序如下

    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace LX1_ILDemo
    {
        class Demo07_Method
        {
            static string binaryName = "Demo07_Method.dll";
            static string namespaceName = "LX1_ILDemo";
            static string typeName = "EmitMethod";
    
            static AssemblyBuilder assemblyBuilder;
            static ModuleBuilder moduleBuilder;
            static TypeBuilder typeBuilder;
    
            public static void Generate()
            {
                InitAssembly();
    
                typeBuilder = moduleBuilder.DefineType(namespaceName + "." + typeName,
                    TypeAttributes.Public | TypeAttributes.Abstract);
    
                /* 生成 public static void Main() */
                GenerateMethods();
    
                SaveAssembly();
                Console.WriteLine("生成成功");
            }
    
            static void GenerateMethods()
            {
                /* public abstract void M1(); */
                MethodBuilder m1 = typeBuilder.DefineMethod("M1",
                    MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                    typeof(void), new Type[] { });
    
                /* public abstract string M2(int arg0,string param1); */
                MethodBuilder m2 = typeBuilder.DefineMethod("M2",
                   MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                   typeof(string), new Type[] { typeof(int), typeof(string), typeof(object) });
    
                m2.DefineParameter(1, ParameterAttributes.None, "arg0");
                m2.DefineParameter(2, ParameterAttributes.None, "param1");
                m2.DefineParameter(3, ParameterAttributes.None, "param2");
    
                /* public abstract string mdefault(int arg1 =4 ); */
                MethodBuilder m3 = typeBuilder.DefineMethod("mdefault",
                   MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                   typeof(string), new Type[] { typeof(int) });
    
                ParameterBuilder m3p1 = m3.DefineParameter(1, ParameterAttributes.HasDefault | ParameterAttributes.Optional, "arg1");
                m3p1.SetConstant(4);
    
                /* public abstract string mref(ref dobule arg2); */
                MethodBuilder m4 = typeBuilder.DefineMethod("mref",
                   MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                   typeof(string), new Type[] { Type.GetType("System.Double&") });
    
                ParameterBuilder m4p1 = m4.DefineParameter(1, ParameterAttributes.Out, "arg2");
    
    
                /* public abstract string mout(out int arg3 ); */
                MethodBuilder m5 = typeBuilder.DefineMethod("mout",
                   MethodAttributes.Public | MethodAttributes.Abstract | MethodAttributes.Virtual,
                   typeof(string), new Type[] { typeof(int), typeof(int) });
    
                ParameterBuilder m5p1 = m5.DefineParameter(1, ParameterAttributes.Out, "arg3");
            }
    
    
            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
  • 相关阅读:
    WDNMD组——项目需求分析
    2020软件工程作业——团队03
    2020软件工程作业——团队02
    WDNMD——团队展示
    spring boot:redis+lua实现顺序自增的唯一id发号器(spring boot 2.3.1)
    linux(centos8):安装kubernetes worker节点并加入到kubernetes集群(kubernetes 1.18.3)
    linux(centos8):kubernetes安装的准备工作
    kubernetes:用label让pod在指定的node上运行(kubernetes1.18.3)
    kubernetes:用kubeadm管理token(kubernetes 1.18.3)
    linux(centos8):kubeadm单机安装kubernetes(kubernetes 1.18.3)
  • 原文地址:https://www.cnblogs.com/tkt2016/p/8617438.html
Copyright © 2020-2023  润新知