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 開始
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實用指南-創建方法和定義參數