using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Globalization;

public class Test
{
    private delegate int HelloDelegate(string msg, int ret);

    public static void Main()
    {
        //------------  创建动态方法  START ----------------------------------
        Type[] helloArgs = { typeof(string), typeof(int) };//方法参数类型

        DynamicMethod hello = new DynamicMethod("Hello",typeof(int),helloArgs,typeof(string).Module);

        Type[] writeStringArgs = { typeof(string) };

        MethodInfo writeString = typeof(Console).GetMethod("WriteLine",writeStringArgs);

        ILGenerator il = hello.GetILGenerator(256);//生成中间语言(MSIL)指令

        il.Emit(OpCodes.Ldarg_0);//将指定指令放入指令流
       
        il.EmitCall(OpCodes.Call, writeString, null);//将Call或callvirt指令放到指令流,以便调用varargs方法

        il.Emit(OpCodes.Ldarg_1);//将指定指令放入指令流
        il.Emit(OpCodes.Ret);//将指定指令放入指令流

        hello.DefineParameter(1, ParameterAttributes.In, "message");//定义动态方法的参数
        hello.DefineParameter(2, ParameterAttributes.In, "valueToReturn");//定义动态方法的参数

        HelloDelegate hi = (HelloDelegate)hello.CreateDelegate(typeof(HelloDelegate));//完成动态方法并创建一个可用于执行该方法的委托
        //此时 hi 即为可以调用的方法名,真正的方法名是 Hello , hi只是用委托的方式调用,以下还可以用Invoke方式调用

        //------------- 创建动态方法   END -----------------------

        //------------ 以下为调用部分 ----------------------------
        Console.WriteLine("\r\nUse the delegate to execute the dynamic method:");
        Console.ReadLine();
        int retval = hi("\r\nHello, World!", 42);
        Console.ReadLine();
        Console.WriteLine("Invoking delegate hi(\"Hello, World!\", 42) returned: " + retval);
        Console.ReadLine();
        retval = hi("\r\nHi, Mom!", 5280);
        Console.ReadLine();
        Console.WriteLine("Invoking delegate hi(\"Hi, Mom!\", 5280) returned: " + retval);
        Console.ReadLine();
        Console.WriteLine("\r\nUse the Invoke method to execute the dynamic method:");
        Console.ReadLine();
        object[] invokeArgs = { "\r\nHello, World!", 42 };
        Console.ReadLine();
        object objRet = hello.Invoke(null, BindingFlags.ExactBinding, null, invokeArgs, new CultureInfo("en-us"));//调用动态方法
        Console.WriteLine("hello.Invoke returned: " + objRet);
        Console.ReadLine();
        Console.WriteLine("\r\n ----- Display information about the dynamic method -----");
        Console.ReadLine();
        Console.WriteLine("\r\nMethod Attributes: {0}", hello.Attributes);//创建动态方法指定的属性
        Console.ReadLine();
        Console.WriteLine("\r\nCalling convention: {0}", hello.CallingConvention);//创建动态方法时指定的调用约定
        Console.ReadLine();
        if (hello.DeclaringType == null)//获取动态方法,对于动态方法类型始终为null
        {
            Console.WriteLine("\r\nDeclaringType is always null for dynamic methods.");
            Console.ReadLine();
        }
        else
        {
            Console.WriteLine("DeclaringType: {0}", hello.DeclaringType);
            Console.ReadLine();
        }

        if (hello.InitLocals)//获取或设置一个值,该值指示方法中的局部变量是否初始化为零
        {
            Console.Write("\r\nThis method contains verifiable code.");
            Console.ReadLine();
        }
        else
        {
            Console.Write("\r\nThis method contains unverifiable code.");
            Console.ReadLine();
        }
        Console.WriteLine(" (InitLocals = {0})", hello.InitLocals);
        Console.ReadLine();
        Console.WriteLine("\r\nModule: {0}", hello.Module);//获取动态方法逻辑关联的模块
        Console.ReadLine();

        Console.WriteLine("\r\nName: {0}", hello.Name);//获取动态方法的名称
        Console.ReadLine();

        if (hello.ReflectedType == null)//获取在反射中用于获取方法的类
        {
            Console.WriteLine("\r\nReflectedType is null.");
            Console.ReadLine();
        }
        else
        {
            Console.WriteLine("\r\nReflectedType: {0}", hello.ReflectedType);
            Console.ReadLine();
        }

        if (hello.ReturnParameter == null)//获取动态方法的返回参数
        {
            Console.WriteLine("\r\nMethod has no return parameter.");
            Console.ReadLine();
        }
        else
        {
            Console.WriteLine("\r\nReturn parameter: {0}", hello.ReturnParameter);
            Console.ReadLine();
        }

        Console.WriteLine("\r\nReturn type: {0}", hello.ReturnType);//获取动态方法的返回值类型
        Console.ReadLine();
        if (hello.ReturnType == typeof(void))
        {
            Console.WriteLine("The method has no return type.");
            Console.ReadLine();
        }
        else
        {
            ICustomAttributeProvider caProvider = hello.ReturnTypeCustomAttributes;//获取动态方法的返回类型的自定义属性
            object[] returnAttributes = caProvider.GetCustomAttributes(true);
            if (returnAttributes.Length == 0)
            {
                Console.WriteLine("\r\nThe return type has no custom attributes.");
                Console.ReadLine();
            }
            else
            {
                Console.WriteLine("\r\nThe return type has the following custom attributes:");
                Console.ReadLine();
                foreach (object attr in returnAttributes)
                {
                    Console.WriteLine("\t{0}", attr.ToString());
                }
                Console.ReadLine();
            }
        }

        Console.WriteLine("\r\nToString: {0}", hello.ToString());//返回方法的签名,以字符串表示
        Console.ReadLine();

        ParameterInfo[] parameters = hello.GetParameters();//获取动态方法的参数
        Console.WriteLine("\r\nParameters: name, type, ParameterAttributes");
        Console.ReadLine();
        foreach (ParameterInfo p in parameters)
        {
            Console.WriteLine("\t{0}, {1}, {2}",
                p.Name, p.ParameterType, p.Attributes);
        }
        Console.ReadLine();
    }
}