예제 #1
0
        /// <summary>
        /// 创建表示指定的静态或实例方法的的委托。如果是实例方法,需要将实例对象作为第一个参数;
        /// </summary>
        /// <param name="method">描述委托要表示的静态或实例方法的 <see cref="MethodInfo"/>。</param>
        /// <returns>表示指定的静态或实例方法的委托。</returns>
        /// <remarks>如果是静态方法,则第一个参数无效。对于可变参数方法,只支持固定参数。</remarks>
        /// <exception cref="ArgumentNullException"><paramref name="method"/> 为 <c>null</c>。</exception>
        /// <exception cref="ArgumentException"><paramref name="method"/> 是开放构造方法。</exception>
        /// <exception cref="MethodAccessException">调用方无权访问 <paramref name="method"/>。</exception>
        public static MethodInvoker CreateDelegate(this MethodInfo method)
        {
            CommonExceptions.CheckArgumentNull(method, "method");
            Contract.Ensures(Contract.Result <MethodInvoker>() != null);
            if (method.ContainsGenericParameters)
            {
                // 不能对开放构造方法执行绑定。
                throw CommonExceptions.BindOpenConstructedMethod("method");
            }
            DynamicMethod dlgMethod = new DynamicMethod("MethodInvoker", typeof(object),
                                                        new[] { typeof(object), typeof(object[]) }, method.Module, true);
            ILGenerator il = dlgMethod.GetILGenerator();

            Contract.Assume(il != null);
            ParameterInfo[] parameters = method.GetParametersNoCopy();
            int             len        = parameters.Length;

            // 参数数量检测。
            if (len > 0)
            {
                il.EmitCheckArgumentNull(1, "parameters");
                il.Emit(OpCodes.Ldarg_1);
                il.EmitCheckTargetParameterCount(parameters.Length);
            }
            // 加载实例对象。
            if (!method.IsStatic)
            {
                il.EmitLoadInstance(method, typeof(object), true);
            }
            bool optimizeTailcall = true;

            // 加载方法参数。
            for (int i = 0; i < len; i++)
            {
                il.Emit(OpCodes.Ldarg_1);
                il.EmitInt(i);
                Type paramType = parameters[i].ParameterType;
                if (paramType.IsByRef)
                {
                    paramType = paramType.GetElementType();
                    Converter converter = il.GetConversion(typeof(object), paramType, ConversionType.Explicit);
                    Console.WriteLine(converter);
                    if (converter.NeedEmit)
                    {
                        il.Emit(OpCodes.Ldelem_Ref);
                        converter.Emit(true);
                        LocalBuilder local = il.DeclareLocal(paramType);
                        il.Emit(OpCodes.Stloc, local);
                        il.Emit(OpCodes.Ldloca, local);
                        optimizeTailcall = false;
                    }
                    else
                    {
                        il.Emit(OpCodes.Ldelema, paramType);
                    }
                }
                else
                {
                    il.Emit(OpCodes.Ldelem_Ref);
                    il.EmitConversion(typeof(object), paramType, true, ConversionType.Explicit);
                }
            }
            // 调用函数。
            il.EmitInvokeMethod(method, null, typeof(object), optimizeTailcall);
            return((MethodInvoker)dlgMethod.CreateDelegate(typeof(MethodInvoker)));
        }