internal static ParameterInfo[] GetParametersCached(this MethodBase method)
 {
     ParameterInfo[] pis;
     lock (_ParamInfoCache) {
         if (!_ParamInfoCache.TryGetValue(method, out pis))
         {
             _ParamInfoCache[method] = pis = method.GetParameters();
         }
     }
     return(pis);
 }
Exemple #2
0
        internal static ParameterInfo[] GetParametersCached(this MethodBase method)
        {
            ParameterInfo[] pis;
            lock (_ParamInfoCache) {
                if (!_ParamInfoCache.TryGetValue(method, out pis))
                {
                    pis = method.GetParameters();

                    Type t = method.DeclaringType;
                    if (t != null && TypeUtils.CanCache(t))
                    {
                        _ParamInfoCache[method] = pis;
                    }
                }
            }
            return(pis);
        }
Exemple #3
0
 internal static ParameterInfo[] GetParametersCached(this MethodBase method)
 {
     ParameterInfo[] parameters;
     lock (_ParamInfoCache)
     {
         if (!_ParamInfoCache.TryGetValue(method, out parameters))
         {
             parameters = method.GetParameters();
             Type declaringType = method.DeclaringType;
             if ((declaringType != null) && declaringType.CanCache())
             {
                 _ParamInfoCache[method] = parameters;
             }
         }
     }
     return(parameters);
 }
Exemple #4
0
        internal static ParameterInfo[] GetParametersCached(this MethodBase method)
        {
            ParameterInfo[] pis;
            CacheDict <MethodBase, ParameterInfo[]> pic = s_paramInfoCache;

            if (!pic.TryGetValue(method, out pis))
            {
                pis = method.GetParameters();

                Type t = method.DeclaringType;
                if (t != null && t.CanCache())
                {
                    pic[method] = pis;
                }
            }

            return(pis);
        }
Exemple #5
0
        internal static Delegate CreateObjectArrayDelegate(Type delegateType, Func <object[], object?> handler)
        {
            // We will generate the following code:
            //
            // object ret;
            // object[] args = new object[parameterCount];
            // args[0] = param0;
            // args[1] = param1;
            //  ...
            // try {
            //      ret = handler.Invoke(args);
            // } finally {
            //      param0 = (T0)args[0];   // only generated for each byref argument
            // }
            // return (TRet)ret;
            if (_thunks.TryGetValue(delegateType, out var thunkMethod))
            {
                return(thunkMethod.CreateDelegate(delegateType, handler));
            }

            var delegateInvokeMethod = delegateType.GetInvokeMethod();

            var returnType     = delegateInvokeMethod.ReturnType;
            var hasReturnValue = returnType != typeof(void);

            var parameters = delegateInvokeMethod.GetParameters();
            var paramTypes = new Type[parameters.Length + 1];

            paramTypes[0] = typeof(Func <object[], object>);
            for (var i = 0; i < parameters.Length; i++)
            {
                paramTypes[i + 1] = parameters[i].ParameterType;
            }

            thunkMethod = new DynamicMethod("Thunk", returnType, paramTypes);
            var ilGenerator = thunkMethod.GetILGenerator();

            var argArray = ilGenerator.DeclareLocal(typeof(object[]));
            var retValue = ilGenerator.DeclareLocal(typeof(object));

            // create the argument array
            if (parameters.Length == 0)
            {
                ilGenerator.Emit(OpCodes.Call, _arrayEmpty);
            }
            else
            {
                ilGenerator.Emit(OpCodes.Ldc_I4, parameters.Length);
                ilGenerator.Emit(OpCodes.Newarr, typeof(object));
            }

            ilGenerator.Emit(OpCodes.Stloc, argArray);

            // populate object array
            var hasRefArgs = false;

            for (var i = 0; i < parameters.Length; i++)
            {
                var paramIsByReference = parameters[i].ParameterType.IsByRef;
                var paramType          = parameters[i].ParameterType;
                if (paramIsByReference)
                {
                    paramType = paramType.GetElementType();
                }

                hasRefArgs = hasRefArgs || paramIsByReference;

                ilGenerator.Emit(OpCodes.Ldloc, argArray);
                ilGenerator.Emit(OpCodes.Ldc_I4, i);
                ilGenerator.Emit(OpCodes.Ldarg, i + 1);

                if (paramIsByReference)
                {
                    ilGenerator.Emit(OpCodes.Ldobj, paramType);
                }

                var boxType = ConvertToBoxableType(paramType);
                ilGenerator.Emit(OpCodes.Box, boxType);
                ilGenerator.Emit(OpCodes.Stelem_Ref);
            }

            if (hasRefArgs)
            {
                ilGenerator.BeginExceptionBlock();
            }

            // load delegate
            ilGenerator.Emit(OpCodes.Ldarg_0);

            // load array
            ilGenerator.Emit(OpCodes.Ldloc, argArray);

            // invoke Invoke
            ilGenerator.Emit(OpCodes.Callvirt, _funcInvoke);
            ilGenerator.Emit(OpCodes.Stloc, retValue);

            if (hasRefArgs)
            {
                // copy back ref/out args
                ilGenerator.BeginFinallyBlock();
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (!parameters[i].ParameterType.IsByRef)
                    {
                        continue;
                    }

                    var byrefToType = parameters[i].ParameterType.GetElementType();

                    // update parameter
                    ilGenerator.Emit(OpCodes.Ldarg, i + 1);
                    ilGenerator.Emit(OpCodes.Ldloc, argArray);
                    ilGenerator.Emit(OpCodes.Ldc_I4, i);
                    ilGenerator.Emit(OpCodes.Ldelem_Ref);
                    ilGenerator.Emit(OpCodes.Unbox_Any, byrefToType);
                    ilGenerator.Emit(OpCodes.Stobj, byrefToType);
                }

                ilGenerator.EndExceptionBlock();
            }

            if (hasReturnValue)
            {
                ilGenerator.Emit(OpCodes.Ldloc, retValue);
                ilGenerator.Emit(OpCodes.Unbox_Any, ConvertToBoxableType(returnType));
            }

            ilGenerator.Emit(OpCodes.Ret);

            _thunks[delegateType] = thunkMethod;

            return(thunkMethod.CreateDelegate(delegateType, handler));
        }
Exemple #6
0
        internal static ParameterInfo[] GetParametersCached(this MethodBase method)
        {
            CacheDict <MethodBase, ParameterInfo[]> pic = s_paramInfoCache;

            if (!pic.TryGetValue(method, out ParameterInfo[] pis))
        // We will generate the following code:
        //
        // object ret;
        // object[] args = new object[parameterCount];
        // args[0] = param0;
        // args[1] = param1;
        //  ...
        // try {
        //      ret = handler.Invoke(args);
        // } finally {
        //      param0 = (T0)args[0];   // only generated for each byref argument
        // }
        // return (TRet)ret;
        private static Delegate CreateObjectArrayDelegateRefEmit(Type delegateType, Func <object[], object> handler)
        {
            if (_thunks.TryGetValue(delegateType, out var thunkMethod))
            {
                return(thunkMethod.CreateDelegate(delegateType, handler));
            }

            var delegateInvokeMethod = delegateType.GetInvokeMethod();

            var returnType     = delegateInvokeMethod.ReturnType;
            var hasReturnValue = returnType != typeof(void);

            var parameters = delegateInvokeMethod.GetParameters();
            var paramTypes = new Type[parameters.Length + 1];

            paramTypes[0] = typeof(Func <object[], object>);
            for (var i = 0; i < parameters.Length; i++)
            {
                paramTypes[i + 1] = parameters[i].ParameterType;
            }

            thunkMethod = new DynamicMethod("Thunk", returnType, paramTypes);
            var ilGenerator = thunkMethod.GetILGenerator();

            var argArray = ilGenerator.DeclareLocal(typeof(object[]));
            var retValue = ilGenerator.DeclareLocal(typeof(object));

            // create the argument array
            if (parameters.Length == 0)
            {
                ilGenerator.Emit(OpCodes.Call, _arrayEmpty);
            }
            else
            {
                ilGenerator.Emit(OpCodes.Ldc_I4, parameters.Length);
                ilGenerator.Emit(OpCodes.Newarr, typeof(object));
            }

            ilGenerator.Emit(OpCodes.Stloc, argArray);

            // populate object array
            var hasRefArgs = false;

            for (var i = 0; i < parameters.Length; i++)
            {
                var paramIsByReference = parameters[i].ParameterType.IsByRef;
                var paramType          = parameters[i].ParameterType;
                if (paramIsByReference)
                {
                    paramType = paramType.GetElementType();
                }

                hasRefArgs = hasRefArgs || paramIsByReference;

                ilGenerator.Emit(OpCodes.Ldloc, argArray);
                ilGenerator.Emit(OpCodes.Ldc_I4, i);
                ilGenerator.Emit(OpCodes.Ldarg, i + 1);

                if (paramIsByReference)
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    ilGenerator.Emit(OpCodes.Ldobj, paramType);
                }

                var boxType = ConvertToBoxableType(paramType);
                ilGenerator.Emit(OpCodes.Box, boxType);
                ilGenerator.Emit(OpCodes.Stelem_Ref);
            }

            if (hasRefArgs)
            {
                ilGenerator.BeginExceptionBlock();
            }

            // load delegate
            ilGenerator.Emit(OpCodes.Ldarg_0);

            // load array
            ilGenerator.Emit(OpCodes.Ldloc, argArray);

            // invoke Invoke
            ilGenerator.Emit(OpCodes.Callvirt, _funcInvoke);
            ilGenerator.Emit(OpCodes.Stloc, retValue);

            if (hasRefArgs)
            {
                // copy back ref/out args
                ilGenerator.BeginFinallyBlock();
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (!parameters[i].ParameterType.IsByRef)
                    {
                        continue;
                    }

                    var byrefToType = parameters[i].ParameterType.GetElementType();

                    // update parameter
                    ilGenerator.Emit(OpCodes.Ldarg, i + 1);
                    ilGenerator.Emit(OpCodes.Ldloc, argArray);
                    ilGenerator.Emit(OpCodes.Ldc_I4, i);
                    ilGenerator.Emit(OpCodes.Ldelem_Ref);
                    // ReSharper disable once AssignNullToNotNullAttribute
                    ilGenerator.Emit(OpCodes.Unbox_Any, byrefToType);
                    ilGenerator.Emit(OpCodes.Stobj, byrefToType);
                }

                ilGenerator.EndExceptionBlock();
            }

            if (hasReturnValue)
            {
                ilGenerator.Emit(OpCodes.Ldloc, retValue);
                ilGenerator.Emit(OpCodes.Unbox_Any, ConvertToBoxableType(returnType));
            }

            ilGenerator.Emit(OpCodes.Ret);

            _thunks[delegateType] = thunkMethod;

            return(thunkMethod.CreateDelegate(delegateType, handler));
        }
        // We will generate the following code:
        //
        // object ret;
        // object[] args = new object[parameterCount];
        // args[0] = param0;
        // args[1] = param1;
        //  ...
        // try {
        //      ret = handler.Invoke(args);
        // } finally {
        //      param0 = (T0)args[0];   // only generated for each byref argument
        // }
        // return (TRet)ret;
        private static Delegate CreateObjectArrayDelegateRefEmit(Type delegateType, Func <object[], object> handler)
        {
            DynamicMethod thunkMethod;

            if (!s_thunks.TryGetValue(delegateType, out thunkMethod))
            {
                MethodInfo delegateInvokeMethod = delegateType.GetInvokeMethod();

                Type returnType     = delegateInvokeMethod.ReturnType;
                bool hasReturnValue = returnType != typeof(void);

                ParameterInfo[] parameters = delegateInvokeMethod.GetParametersCached();
                Type[]          paramTypes = new Type[parameters.Length + 1];
                paramTypes[0] = typeof(Func <object[], object>);
                for (int i = 0; i < parameters.Length; i++)
                {
                    paramTypes[i + 1] = parameters[i].ParameterType;
                }

                thunkMethod = new DynamicMethod("Thunk", returnType, paramTypes);
                ILGenerator ilgen = thunkMethod.GetILGenerator();

                LocalBuilder argArray = ilgen.DeclareLocal(typeof(object[]));
                LocalBuilder retValue = ilgen.DeclareLocal(typeof(object));

                // create the argument array
                if (parameters.Length == 0)
                {
                    ilgen.Emit(OpCodes.Call, s_ArrayEmpty);
                }
                else
                {
                    ilgen.Emit(OpCodes.Ldc_I4, parameters.Length);
                    ilgen.Emit(OpCodes.Newarr, typeof(object));
                }
                ilgen.Emit(OpCodes.Stloc, argArray);

                // populate object array
                bool hasRefArgs = false;
                for (int i = 0; i < parameters.Length; i++)
                {
                    bool paramIsByReference = parameters[i].ParameterType.IsByRef;
                    Type paramType          = parameters[i].ParameterType;
                    if (paramIsByReference)
                    {
                        paramType = paramType.GetElementType();
                    }

                    hasRefArgs = hasRefArgs || paramIsByReference;

                    ilgen.Emit(OpCodes.Ldloc, argArray);
                    ilgen.Emit(OpCodes.Ldc_I4, i);
                    ilgen.Emit(OpCodes.Ldarg, i + 1);

                    if (paramIsByReference)
                    {
                        ilgen.Emit(OpCodes.Ldobj, paramType);
                    }
                    Type boxType = ConvertToBoxableType(paramType);
                    ilgen.Emit(OpCodes.Box, boxType);
                    ilgen.Emit(OpCodes.Stelem_Ref);
                }

                if (hasRefArgs)
                {
                    ilgen.BeginExceptionBlock();
                }

                // load delegate
                ilgen.Emit(OpCodes.Ldarg_0);

                // load array
                ilgen.Emit(OpCodes.Ldloc, argArray);

                // invoke Invoke
                ilgen.Emit(OpCodes.Callvirt, s_FuncInvoke);
                ilgen.Emit(OpCodes.Stloc, retValue);

                if (hasRefArgs)
                {
                    // copy back ref/out args
                    ilgen.BeginFinallyBlock();
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        if (parameters[i].ParameterType.IsByRef)
                        {
                            Type byrefToType = parameters[i].ParameterType.GetElementType();

                            // update parameter
                            ilgen.Emit(OpCodes.Ldarg, i + 1);
                            ilgen.Emit(OpCodes.Ldloc, argArray);
                            ilgen.Emit(OpCodes.Ldc_I4, i);
                            ilgen.Emit(OpCodes.Ldelem_Ref);
                            ilgen.Emit(OpCodes.Unbox_Any, byrefToType);
                            ilgen.Emit(OpCodes.Stobj, byrefToType);
                        }
                    }
                    ilgen.EndExceptionBlock();
                }

                if (hasReturnValue)
                {
                    ilgen.Emit(OpCodes.Ldloc, retValue);
                    ilgen.Emit(OpCodes.Unbox_Any, ConvertToBoxableType(returnType));
                }

                ilgen.Emit(OpCodes.Ret);

                s_thunks[delegateType] = thunkMethod;
            }

            return(thunkMethod.CreateDelegate(delegateType, handler));
        }