internal static ParameterInfo[] GetParametersCached(this MethodBase method) { ParameterInfo[] pis; lock (_ParamInfoCache) { if (!_ParamInfoCache.TryGetValue(method, out pis)) { _ParamInfoCache[method] = pis = method.GetParameters(); } } return(pis); }
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); }
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); }
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); }
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)); }
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)); }