现在的位置: 首页 > 综合 > 正文

DynamicMethod ILGenerator.Emit

2012年09月15日 ⁄ 综合 ⁄ 共 7711字 ⁄ 字号 评论关闭


namespace ConsoleApplication
{
    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    using System.Collections.Generic;
    //using System.Text;
    using System.Linq;
    using System.Diagnostics;
    //using System.Linq.Expressions;
    using Microshaoft;
    /// <summary>
    /// Class1 的摘要说明。
    /// </summary>
    public class Class1
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        //[STAThread]
        static void Main(string[] args)
        {
            Person person = new Person();
            string word = "hello";
            Person p = null;
            object[] param = new object[] { word, p, 3 };
            Stopwatch watch1 = new Stopwatch();
            //FastInvokeHandler fastInvoker = DynamicMethodHelper.GetDynamicMethodInvoker(methodInfo);
            Person x = null;
            int y = -1;
            DynamicMethodHelper.DynamicMethodFuncInvokeHandler handler1 = DynamicMethodHelper.GetDynamicMethodFuncInvoker
                                                     (
                                                        person
                                                        ,
                                                        mi =>
                                                        {
                                                            return !mi.IsStatic && mi.Name.Equals("Say");
                                                        }
                                                    );
            DynamicMethodHelper.DynamicMethodFuncInvokeHandler handler2 = DynamicMethodHelper.GetDynamicMethodFuncInvoker<Person>
                                        (
                                            mi =>
                                            {
                                                return mi.IsStatic && mi.Name.Equals("Say");
                                            }
                                        );//.Invoke(person, new object[] { "hihi" });
            CodeTimer.Time
                                (
                                    "串行测试"
                                    , 1
                                    , () =>
                                        {
                                            var parameters = new object[] { "aaa", x, y };
                                            handler1.DynamicInvoke(person, parameters);
                                            Console.WriteLine("实例方法 Say Invoke ref word: {0}, int avi {1}", parameters[0], parameters[2]);
                                            handler1.Invoke(person, parameters);
                                            Console.WriteLine("实例方法 Say Invoke ref word: {0}, int avi {1}", parameters[0], parameters[2]);
                                            string s = (string)handler2.DynamicInvoke(person, new object[] { "bb", x, y });
                                            Console.WriteLine("静态方法 Say DynamicInvoke return: {0}", s);
                                            s = (string)handler2.Invoke(person, new object[] { "bb", x, y });
                                            Console.WriteLine("静态方法 Say Invoke return: {0}", s);
                                        }
        );
            CodeTimer.ParallelTime
                    (
                        "并行测试"
                        , 1
                        , () =>
                        {
                            var parameters = new object[] { "aaa", x, y };
                            handler1.DynamicInvoke(person, parameters);
                            Console.WriteLine("实例方法 Say Invoke ref word: {0}, int avi {1}", parameters[0], parameters[2]);
                            handler1.Invoke(person, parameters);
                            Console.WriteLine("实例方法 Say Invoke ref word: {0}, int avi {1}", parameters[0], parameters[2]);
                            string s = (string)handler2.DynamicInvoke(person, new object[] { "bb", x, y });
                            Console.WriteLine("静态方法 Say DynamicInvoke return: {0}", s);
                            s = (string)handler2.Invoke(person, new object[] { "bb", x, y });
                            Console.WriteLine("静态方法 Say Invoke return: {0}", s);
                        }
);
            Console.ReadLine();
        }
    }
    public class Person
    {
        public void Say(ref string word, out Person p, int avi)
        {
            word = "instance " + avi.ToString();
            //Console.WriteLine(word);
            p = new Person();
            //return 100;
        }
        public static string Say(string word)
        {
            //Console.WriteLine("Static Say");
            return "return static " + word;
        }
    }
}
namespace Microshaoft
{
    using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;
    public static class CodeTimer
    {
        public static void Initialize()
        {
            Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
            Time("", 1, () => { });
        }
        public static void ParallelTime(string name, int iteration, Action action)
        {
            InternalIterationProcess
                     (
                        name
                        , iteration
                        , () =>
                            {
                                 Parallel.For
                                            (
                                                0
                                                , iteration
                                                , new ParallelOptions()
                                                        {
                                                            MaxDegreeOfParallelism = 4,
                                                            TaskScheduler = null
                                                        }
                                                , i =>
                                                {
                                                    action();
                                                }
                                            );
                            }
                        );
        }
        private static void InternalIterationProcess(string name, int iteration, Action action)
        {
            if (string.IsNullOrEmpty(name))
            {
                return;
            }
            // 1.
            ConsoleColor currentForeColor = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine(name);
            // 2.
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            int[] gcCounts = new int[GC.MaxGeneration + 1];
            for (int i = 0; i <= GC.MaxGeneration; i++)
            {
                gcCounts[i] = GC.CollectionCount(i);
            }
            // 3.
            Stopwatch watch = new Stopwatch();
            watch.Start();
            ulong cycleCount = GetCycleCount();
            action();
            ulong cpuCycles = GetCycleCount() - cycleCount;
            watch.Stop();
            // 4.
            Console.ForegroundColor = currentForeColor;
            Console.WriteLine("\tTime Elapsed:\t" + watch.ElapsedMilliseconds.ToString("N0") + "ms");
            Console.WriteLine("\tCPU Cycles:\t" + cpuCycles.ToString("N0"));
            // 5.
            for (int i = 0; i <= GC.MaxGeneration; i++)
            {
                int count = GC.CollectionCount(i) - gcCounts[i];
                Console.WriteLine("\tGen " + i + ": \t\t" + count);
            }
            Console.WriteLine();
        }
        public static void Time(string name, int iteration, Action action)
        {
            InternalIterationProcess
                                (
                                    name
                                    , iteration
                                    , () =>
                                        {
                                            for (int i = 0; i < iteration; i++)
                                            {
                                                action();
                                            }
                                        }
                                    );
        }
        private static ulong GetCycleCount()
        {
            ulong cycleCount = 0;
            QueryThreadCycleTime(GetCurrentThread(), ref cycleCount);
            return cycleCount;
        }
        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool QueryThreadCycleTime(IntPtr threadHandle, ref ulong cycleTime);
        [DllImport("kernel32.dll")]
        static extern IntPtr GetCurrentThread();
    }
}
namespace Microshaoft
{
    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    using System.Collections.Generic;
    using System.Text;
    using System.Linq;
    using System.Diagnostics;
    public class DynamicMethodHelper
    {
        public delegate object DynamicMethodFuncInvokeHandler(object target, object[] parameters);
        public static DynamicMethodFuncInvokeHandler GetDynamicMethodFuncInvoker(string typeName, Func<MethodInfo, bool> predicateFunc)
        {
            MethodInfo methodInfo = Type.GetType(typeName).GetMethods().First
                                                    (
                                                        mi =>
                                                        {
                                                            return predicateFunc(mi);
                                                        }
                                                    );
            DynamicMethod dynamicMethod = GetDynamicMethod(methodInfo);
            return (DynamicMethodFuncInvokeHandler)dynamicMethod.CreateDelegate(typeof(DynamicMethodFuncInvokeHandler));
        }
        public static DynamicMethodFuncInvokeHandler GetDynamicMethodFuncInvoker<TTarget>(Func<MethodInfo, bool> predicateFunc)
        {
            MethodInfo methodInfo = typeof(TTarget).GetMethods().First
                                                    (
                                                        mi =>
                                                        {
                                                            return predicateFunc(mi);
                                                        }
                                                    );
            DynamicMethod dynamicMethod = GetDynamicMethod(methodInfo);
            return (DynamicMethodFuncInvokeHandler)dynamicMethod.CreateDelegate(typeof(DynamicMethodFuncInvokeHandler));
        }
        public static DynamicMethodFuncInvokeHandler GetDynamicMethodFuncInvoker(object target, Func<MethodInfo, bool> predicateFunc)
        {
            MethodInfo methodInfo = target.GetType().GetMethods().First
                                                    (
                                                        mi =>
                                                        {
                                                            return predicateFunc(mi);
                                                        }
                                                    );
            DynamicMethod dynamicMethod = GetDynamicMethod(methodInfo);
            return (DynamicMethodFuncInvokeHandler)dynamicMethod.CreateDelegate(typeof(DynamicMethodFuncInvokeHandler));
        }
        private static DynamicMethod GetDynamicMethod(MethodInfo methodInfo)
        {
            int i = 0;
            var list = methodInfo.GetParameters().ToList();
            DynamicMethod dynamicMethod = new DynamicMethod
                                                    (
                                                        string.Empty
                                                        , typeof(object)
                                                        , new Type[] 
                                                                {
                                                                    typeof(object)
                                                                    , typeof(object[])
                                                                }
                                                         , methodInfo.DeclaringType.Module
                                                      );
            ILGenerator ilg = dynamicMethod.GetILGenerator();
            if (!methodInfo.IsStatic)
            {
                ilg.Emit(OpCodes.Ldarg_0);
            }
            i = 0;
            list.ForEach
                            (
                                pi =>
                                {
                                    Type pt;
                                    if (pi.ParameterType.IsByRef)
                                    {
                                        pt = pi.ParameterType.GetElementType();
                                    }
                                    else
                                    {
                                        pt = pi.ParameterType;
                                    }
                                    //paramTypes[i] = pt;
                                    LocalBuilder lb = ilg.DeclareLocal(pt, true);
                                    ilg.Emit(OpCodes.Ldarg_1);
                                    EmitFastInt(ilg, i);
                                    ilg.Emit(OpCodes.Ldelem_Ref);
                                    EmitCastToReference(ilg, pt);
                                    ilg.Emit(OpCodes.Stloc, lb);
                                    if (pi.ParameterType.IsByRef)
                                    {
                                        ilg.Emit(OpCodes.Ldloca_S, lb);
                                        ilg.Emit(OpCodes.Ldarg_1);
                                        EmitFastInt(ilg, i);
                                        ilg.Emit(OpCodes.Ldloc, lb);
                                        if (lb.LocalType.IsValueType)
                                        {
                                            ilg.Emit(OpCodes.Box, lb.LocalType);
                                        }
                                        ilg.Emit(OpCodes.Stelem_Ref);
                                    }
                                    else
                                    {
                                        ilg.Emit(OpCodes.Ldloc, lb);
                                    }
                                    i++;
                                }
                            );
            if (methodInfo.IsStatic)
            {
                ilg.EmitCall(OpCodes.Call, methodInfo, null);
            }
            else
            {
                ilg.EmitCall(OpCodes.Callvirt, methodInfo, null);
            }
            if (methodInfo.ReturnType == typeof(void))
            {
                ilg.Emit(OpCodes.Ldnull);
            }
            else
            {
                EmitBoxIfNeeded(ilg, methodInfo.ReturnType);
            }
            ilg.Emit(OpCodes.Ret);
            return dynamicMethod;
        }
        private static void EmitCastToReference(ILGenerator ilg, Type type)
        {
            if (type.IsValueType)
            {
                ilg.Emit(OpCodes.Unbox_Any, type);
            }
            else
            {
                ilg.Emit(OpCodes.Castclass, type);
            }
        }
        private static void EmitBoxIfNeeded(ILGenerator ilg, Type type)
        {
            if (type.IsValueType)
            {
                ilg.Emit(OpCodes.Box, type);
            }
        }
        private static void EmitFastInt(ILGenerator il, int value)
        {
            switch (value)
            {
                case -1:
                    il.Emit(OpCodes.Ldc_I4_M1);
                    return;
                case 0:
                    il.Emit(OpCodes.Ldc_I4_0);
                    return;
                case 1:
                    il.Emit(OpCodes.Ldc_I4_1);
                    return;
                case 2:
                    il.Emit(OpCodes.Ldc_I4_2);
                    return;
                case 3:
                    il.Emit(OpCodes.Ldc_I4_3);
                    return;
                case 4:
                    il.Emit(OpCodes.Ldc_I4_4);
                    return;
                case 5:
                    il.Emit(OpCodes.Ldc_I4_5);
                    return;
                case 6:
                    il.Emit(OpCodes.Ldc_I4_6);
                    return;
                case 7:
                    il.Emit(OpCodes.Ldc_I4_7);
                    return;
                case 8:
                    il.Emit(OpCodes.Ldc_I4_8);
                    return;
            }
            if (value > -129 && value < 128)
            {
                il.Emit(OpCodes.Ldc_I4_S, (SByte)value);
            }
            else
            {
                il.Emit(OpCodes.Ldc_I4, value);
            }
        }
    }
}

抱歉!评论已关闭.