调用 OpCode 的 docs 表示可以以非虚拟方式调用虚拟方法。它只会根据 IL 中的编译类型而不是运行时类型信息来调用方法。
但是,据我所知,如果您以非虚拟方式调用虚拟方法,该方法将无法验证。这是一个简短的测试程序,我们将在其中动态发出 IL 以调用方法(虚拟或非虚拟)、编译并运行它:
using System.Reflection;
using System.Reflection.Emit;
public class Program
{
public static void Main()
{
// Base parameter, Base method info
CreateAndInvokeMethod(false, new Base(), typeof(Base), typeof(Base).GetMethod("Test"));
CreateAndInvokeMethod(true, new Base(), typeof(Base), typeof(Base).GetMethod("Test"));
CreateAndInvokeMethod(false, new C(), typeof(Base), typeof(Base).GetMethod("Test"));
CreateAndInvokeMethod(true, new C(), typeof(Base), typeof(Base).GetMethod("Test"));
Console.WriteLine();
// Base parameter, C method info
CreateAndInvokeMethod(false, new Base(), typeof(Base), typeof(C).GetMethod("Test"));
CreateAndInvokeMethod(true, new Base(), typeof(Base), typeof(C).GetMethod("Test"));
CreateAndInvokeMethod(false, new C(), typeof(Base), typeof(C).GetMethod("Test"));
CreateAndInvokeMethod(true, new C(), typeof(Base), typeof(C).GetMethod("Test"));
Console.WriteLine();
// C parameter, C method info
CreateAndInvokeMethod(false, new C(), typeof(C), typeof(C).GetMethod("Test"));
CreateAndInvokeMethod(true, new C(), typeof(C), typeof(C).GetMethod("Test"));
}
private static void CreateAndInvokeMethod(bool useVirtual, Base instance, Type parameterType, MethodInfo methodInfo)
{
var dynMethod = new DynamicMethod("test", typeof (string),
new Type[] { parameterType });
var gen = dynMethod.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
OpCode code = useVirtual ? OpCodes.Callvirt : OpCodes.Call;
gen.Emit(code, methodInfo);
gen.Emit(OpCodes.Ret);
string res;
try
{
res = (string)dynMethod.Invoke(null, new object[] { instance });
}
catch (TargetInvocationException ex)
{
var e = ex.InnerException;
res = string.Format("{0}: {1}", e.GetType(), e.Message);
}
Console.WriteLine("UseVirtual: {0}, Result: {1}", useVirtual, res);
}
}
public class Base
{
public virtual string Test()
{
return "Base";
}
}
public class C : Base
{
public override string Test()
{
return "C";
}
}
输出:
UseVirtual:False,结果:System.Security.VerificationException:操作可能会破坏运行时的稳定性。
UseVirtual: True, 结果: Base
UseVirtual:False,结果:System.Security.VerificationException:操作可能会破坏运行时的稳定性。
UseVirtual: True, 结果: C
UseVirtual:False,结果:System.Security.VerificationException:操作可能会破坏运行时的稳定性。
UseVirtual:True,结果:System.Security.VerificationException:操作可能会破坏运行时的稳定性。
UseVirtual:False,结果:System.Security.VerificationException:操作可能会破坏运行时的稳定性。
UseVirtual:True,结果:System.Security.VerificationException:操作可能会破坏运行时的稳定性。
UseVirtual:False,结果:System.Security.VerificationException:操作可能会破坏运行时的稳定性。
UseVirtual: True, 结果: C