带参数的 C# 反射发出调用
C# Reflection Emit Call with parameter
我想用 reflection.emit
API 参数调用一个函数。以下是我目前所拥有的。但是当我 运行 它时,它会抛出以下异常:System.InvalidProgramException : Common Language Runtime detected an invalid program
。所以我的问题是我下面的代码片段有什么问题?有人可以帮我吗?
public class Test
{
public void test()
{
Func<int, long> realSquareFunc = (val) => val * val;
Type[] methodArgs = { typeof(int) };
DynamicMethod squareIt = new DynamicMethod(
"SquareIt",
typeof(long),
methodArgs,
typeof(Test).Module)
;
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Save parameter on stack
il.Emit(OpCodes.Call, realSquareFunc.Method); // Call function with input as parameter
il.Emit(OpCodes.Ret); // Return value from function call before
var myMethod = (Func<int, long>)squareIt.CreateDelegate(realSquareFunc.GetType());
var result = myMethod.Invoke(4); // Should be 16 (4*4)
}
}
如果调用的方法是静态方法,您的代码将按原样运行:
public static long RealSquare(int val) => val * val;
public void test()
{
Func<int, long> realSquareFunc = RealSquare;
// ...
然而,realSquareFunc = (val) => val * val
lambda 实际上被编译为隐藏class 的实例方法。要调用实例方法,必须先将实例压入堆栈,然后再压入方法参数。实例方法调用通常也使用 Callvirt
操作码(不管它们是否是虚拟的,因为此操作码会进行空引用检查):
public class Test
{
public long RealSquare(int val) => val * val;
public void test()
{
Func<int, long> realSquareFunc = RealSquare;
// pass the instance we want to call the method on in as well
Type[] methodArgs = { typeof(Test), typeof(int) };
DynamicMethod squareIt = new DynamicMethod(
"SquareIt",
typeof(long),
methodArgs,
typeof(Test).Module)
;
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Push the target instance onto stack
il.Emit(OpCodes.Ldarg_1); // Save parameter on stack
il.Emit(OpCodes.Callvirt, realSquareFunc.Method); // Call function with input as parameter
il.Emit(OpCodes.Ret); // Return value from function call before
var myMethod = (Func<Test, int, long>)squareIt.CreateDelegate(typeof(Func<Test, int, long>));
var result = myMethod.Invoke(this, 4); // Should be 16 (4*4)
}
}
直接调用 lambda 的目标方法 由于涉及编译器生成的 class 更复杂,但是如果你想调用一般的委托它像这样工作:
public class Test
{
public void test()
{
Func<int, long> realSquareFunc = (val) => val * val;
// pass the delegate we want to call into the method
Type[] methodArgs = { realSquareFunc.GetType(), typeof(int) };
DynamicMethod squareIt = new DynamicMethod(
"SquareIt",
typeof(long),
methodArgs,
typeof(Test).Module)
;
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Push the delegate onto stack
il.Emit(OpCodes.Ldarg_1); // Save parameter on stack
il.Emit(OpCodes.Callvirt, realSquareFunc.GetType().GetMethod("Invoke")); // Invoke delegate
il.Emit(OpCodes.Ret); // Return value from function call before
var myMethod = (Func<Func<int, long>, int, long>)squareIt
.CreateDelegate(typeof(Func<Func<int, long>, int, long>));
var result = myMethod.Invoke(realSquareFunc, 4); // Should be 16 (4*4)
}
}
我想用 reflection.emit
API 参数调用一个函数。以下是我目前所拥有的。但是当我 运行 它时,它会抛出以下异常:System.InvalidProgramException : Common Language Runtime detected an invalid program
。所以我的问题是我下面的代码片段有什么问题?有人可以帮我吗?
public class Test
{
public void test()
{
Func<int, long> realSquareFunc = (val) => val * val;
Type[] methodArgs = { typeof(int) };
DynamicMethod squareIt = new DynamicMethod(
"SquareIt",
typeof(long),
methodArgs,
typeof(Test).Module)
;
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Save parameter on stack
il.Emit(OpCodes.Call, realSquareFunc.Method); // Call function with input as parameter
il.Emit(OpCodes.Ret); // Return value from function call before
var myMethod = (Func<int, long>)squareIt.CreateDelegate(realSquareFunc.GetType());
var result = myMethod.Invoke(4); // Should be 16 (4*4)
}
}
如果调用的方法是静态方法,您的代码将按原样运行:
public static long RealSquare(int val) => val * val;
public void test()
{
Func<int, long> realSquareFunc = RealSquare;
// ...
然而,realSquareFunc = (val) => val * val
lambda 实际上被编译为隐藏class 的实例方法。要调用实例方法,必须先将实例压入堆栈,然后再压入方法参数。实例方法调用通常也使用 Callvirt
操作码(不管它们是否是虚拟的,因为此操作码会进行空引用检查):
public class Test
{
public long RealSquare(int val) => val * val;
public void test()
{
Func<int, long> realSquareFunc = RealSquare;
// pass the instance we want to call the method on in as well
Type[] methodArgs = { typeof(Test), typeof(int) };
DynamicMethod squareIt = new DynamicMethod(
"SquareIt",
typeof(long),
methodArgs,
typeof(Test).Module)
;
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Push the target instance onto stack
il.Emit(OpCodes.Ldarg_1); // Save parameter on stack
il.Emit(OpCodes.Callvirt, realSquareFunc.Method); // Call function with input as parameter
il.Emit(OpCodes.Ret); // Return value from function call before
var myMethod = (Func<Test, int, long>)squareIt.CreateDelegate(typeof(Func<Test, int, long>));
var result = myMethod.Invoke(this, 4); // Should be 16 (4*4)
}
}
直接调用 lambda 的目标方法 由于涉及编译器生成的 class 更复杂,但是如果你想调用一般的委托它像这样工作:
public class Test
{
public void test()
{
Func<int, long> realSquareFunc = (val) => val * val;
// pass the delegate we want to call into the method
Type[] methodArgs = { realSquareFunc.GetType(), typeof(int) };
DynamicMethod squareIt = new DynamicMethod(
"SquareIt",
typeof(long),
methodArgs,
typeof(Test).Module)
;
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Push the delegate onto stack
il.Emit(OpCodes.Ldarg_1); // Save parameter on stack
il.Emit(OpCodes.Callvirt, realSquareFunc.GetType().GetMethod("Invoke")); // Invoke delegate
il.Emit(OpCodes.Ret); // Return value from function call before
var myMethod = (Func<Func<int, long>, int, long>)squareIt
.CreateDelegate(typeof(Func<Func<int, long>, int, long>));
var result = myMethod.Invoke(realSquareFunc, 4); // Should be 16 (4*4)
}
}