1. 程式人生 > >MSIL實用指南-創建方法和定義參數

MSIL實用指南-創建方法和定義參數

ring get 依次 creat public object turn itme bst

本篇講解實現創建方法、指定參數的名稱、實現參數加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實用指南-創建方法和定義參數