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

Posted TKT2016

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 

以上是关于MSIL实用指南-创建方法和定义参数的主要内容,如果未能解决你的问题,请参考以下文章

MSIL实用指南-生成属性

MSIL实用指南-类相关生成

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

MSIL实用指南-方法的调用

MSIL实用指南-比较运算

MSIL实用指南-加载nullstringlongfloatdouble等值