"Exception has been thrown by the target of an invocation." 使用两个参数实现函数时出现问题
"Exception has been thrown by the target of an invocation." issue while implementing function with two params
我正在尝试为动态生成的 class/method 实现接口。对于带有一个参数的方法(在代码中注释),该实现是可以的。但是当方法有两个或更多参数时,它会抛出 "Exception has been thrown by the target of an invocation"。
无法弄清楚两个参数有什么问题?任何帮助,将不胜感激。
下面是我的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using System.Reflection;
using System.Reflection.Emit;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
namespace ConsoleApplication7
{
public class Foo
{
public string Bar(string m)
{
return m;
}
}
public interface IFoo
{
string Barz(int i, int s);
//string Barz(int i);// works good
}
public class Program
{
public string my(int w, int s)
{
return (s + w).ToString();
}
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void TestMethod()
{
var ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.RunAndSave);
var mb = ab.DefineDynamicModule("Test");
var tb = mb.DefineType("Foo", typeof(Foo).Attributes, typeof(Foo));
tb.AddInterfaceImplementation(typeof(IFoo));
foreach (var imethod in typeof(IFoo).GetMethods())
{
var method =
tb.DefineMethod
(
"@@" + imethod.Name,
MethodAttributes.Private | MethodAttributes.Static,
CallingConventions.Standard,
imethod.ReturnType,
imethod.GetParameters().Select(n => n.ParameterType).ToArray()
);
var thisParameter = Expression.Parameter(typeof(IFoo), "this");
var param = new ParameterExpression[] { Expression.Parameter(typeof(int)), Expression.Parameter(typeof(int)) };
var bodyExpression =
Expression.Lambda<Func<int,int, string>>(
Expression.Call(
Expression.New(typeof(Program)),
typeof(Program).GetMethod("my", new Type[] { typeof(int), typeof(int) }), param
), param);
//var y = bodyExpression.Compile();//compiles good
// var p = y.Invoke(200, "");//invocation is ok
bodyExpression.CompileToMethod(method);
var mp = imethod.GetParameters().Select(r => r.ParameterType).ToArray();
var stub =
tb.DefineMethod(imethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.Standard,
imethod.ReturnType, mp);
var il = stub.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, method, null);
il.Emit(OpCodes.Ret);
tb.DefineMethodOverride(stub, imethod);
}
var type = tb.CreateType();
ab.Save("test.dll");
var obj = CreateAndInvoke(type, null, "Barz", null);
Console.ReadLine();
}
public static object CreateAndInvoke(Type typeName, object[] constructorArgs, string methodName, object[] methodArgs)
{
Type type = typeName;
object instance = Activator.CreateInstance(type);
object[] a = new object[] { 900 ,0};
MethodInfo method = type.GetMethod(methodName);
return method.Invoke(instance, a);//issue over here
}
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public static void Main(string[] args)
{
new Program().TestMethod();
}
}
}
Unable to figure out what is wrong with two args? Any help would be appreciated.
代码生成的代码没有任何意义。它被编写为为任意方法调用生成一个存根,然后将单个参数传递给该方法,而不管该方法的参数。那是完全错误的;该代码仅适用于一个参数的方法。
运行时将在验证或 jitting 期间识别该问题,并给出无效程序异常,而不是 运行 和未对齐堆栈。
我正在尝试为动态生成的 class/method 实现接口。对于带有一个参数的方法(在代码中注释),该实现是可以的。但是当方法有两个或更多参数时,它会抛出 "Exception has been thrown by the target of an invocation"。 无法弄清楚两个参数有什么问题?任何帮助,将不胜感激。 下面是我的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using System.Reflection;
using System.Reflection.Emit;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Controllers;
namespace ConsoleApplication7
{
public class Foo
{
public string Bar(string m)
{
return m;
}
}
public interface IFoo
{
string Barz(int i, int s);
//string Barz(int i);// works good
}
public class Program
{
public string my(int w, int s)
{
return (s + w).ToString();
}
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void TestMethod()
{
var ab = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.RunAndSave);
var mb = ab.DefineDynamicModule("Test");
var tb = mb.DefineType("Foo", typeof(Foo).Attributes, typeof(Foo));
tb.AddInterfaceImplementation(typeof(IFoo));
foreach (var imethod in typeof(IFoo).GetMethods())
{
var method =
tb.DefineMethod
(
"@@" + imethod.Name,
MethodAttributes.Private | MethodAttributes.Static,
CallingConventions.Standard,
imethod.ReturnType,
imethod.GetParameters().Select(n => n.ParameterType).ToArray()
);
var thisParameter = Expression.Parameter(typeof(IFoo), "this");
var param = new ParameterExpression[] { Expression.Parameter(typeof(int)), Expression.Parameter(typeof(int)) };
var bodyExpression =
Expression.Lambda<Func<int,int, string>>(
Expression.Call(
Expression.New(typeof(Program)),
typeof(Program).GetMethod("my", new Type[] { typeof(int), typeof(int) }), param
), param);
//var y = bodyExpression.Compile();//compiles good
// var p = y.Invoke(200, "");//invocation is ok
bodyExpression.CompileToMethod(method);
var mp = imethod.GetParameters().Select(r => r.ParameterType).ToArray();
var stub =
tb.DefineMethod(imethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.Standard,
imethod.ReturnType, mp);
var il = stub.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Call, method, null);
il.Emit(OpCodes.Ret);
tb.DefineMethodOverride(stub, imethod);
}
var type = tb.CreateType();
ab.Save("test.dll");
var obj = CreateAndInvoke(type, null, "Barz", null);
Console.ReadLine();
}
public static object CreateAndInvoke(Type typeName, object[] constructorArgs, string methodName, object[] methodArgs)
{
Type type = typeName;
object instance = Activator.CreateInstance(type);
object[] a = new object[] { 900 ,0};
MethodInfo method = type.GetMethod(methodName);
return method.Invoke(instance, a);//issue over here
}
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public static void Main(string[] args)
{
new Program().TestMethod();
}
}
}
Unable to figure out what is wrong with two args? Any help would be appreciated.
代码生成的代码没有任何意义。它被编写为为任意方法调用生成一个存根,然后将单个参数传递给该方法,而不管该方法的参数。那是完全错误的;该代码仅适用于一个参数的方法。
运行时将在验证或 jitting 期间识别该问题,并给出无效程序异常,而不是 运行 和未对齐堆栈。