public static Delegate CreateMethodCaller(Type delegateType, MethodInfo method) { // arguments checks if (!typeof(Delegate).IsAssignableFrom(delegateType)) { throw new ArgumentException("delegateType does not represents a delegate", nameof(delegateType)); } // read delegate info var methodInfo = delegateType.GetMethod("Invoke"); var delegateArgs = methodInfo?.GetParameters().Select(x => x.ParameterType).ToArray() ?? Type.EmptyTypes; var retType = methodInfo.ReturnType != typeof(void) ? methodInfo.ReturnType : null; // read method info var methodArgs = method.GetParameters().Select(x => x.ParameterType).ToArray(); var argsCount = methodArgs.Length; // Type this_ = method.IsStatic ? null : (method.DeclaringType.IsValueType ? method.DeclaringType.MakeByRefType() : method.DeclaringType); var arguments = Enumerable.Empty <Type>(); if (this_ != null) { arguments = arguments.Append(this_); argsCount++; } arguments = arguments.Concat(methodArgs); if (delegateArgs.Length != argsCount) { throw new Exception("deletage's arguments count does not match method's arguments count"); } DynamicMethod wrapper = new DynamicMethod($"method_{method.DeclaringType.Name}_{method.Name}", retType, arguments.ToArray(), typeof(Dynamic), true); IILGenerator gen = wrapper.GetILGenerator().AsInterface(); int argIndex = 0; if (this_ != null) { if (this_.IsValueType) { // Struct; gen.Ldarga_S((byte)argIndex++); } else { // Class; ref Struct; gen.Ldarg((byte)argIndex++); } } for (int i = 0; i < methodArgs.Length; i++) { gen.Ldarg((byte)argIndex++); } gen .Call(method) .Ret(); return(wrapper.CreateDelegate(delegateType)); }