【发布时间】:2022-01-27 23:26:10
【问题描述】:
我正在尝试使用System.Reflection.Emit 调用外部委托的方法动态构建类型。但是,当我尝试调用此方法时,我的程序崩溃,并在方法调用的标题中出现异常。到目前为止,这是我的代码:
private static void TestMethodReal() => Console.Out.WriteLine("Inside TestMethod");
// In Main()
var method = typeof(Program).GetMethod(nameof(TestMethodReal), BindingFlags.Static | BindingFlags.NonPublic)!;
var builder = MyTypeBuilder.GetTypeBuilder("TestType");
var testMethod = builder.DefineMethod("TestMethod", MethodAttributes.Public, typeof(void), Type.EmptyTypes);
var generator = testMethod.GetILGenerator();
generator.EmitCall(OpCodes.Callvirt, method, null);
generator.Emit(OpCodes.Ret);
dynamic inst = Activator.CreateInstance(builder.CreateType()!)!;
inst.TestMethod(); // <--- Exception is thrown here
MyTypeBuilder 类和GetTypeBuilder 方法来自this 答案,稍作修改以接受类型名称的参数。
这个程序应该用一个名为TestMethod的方法创建一个新的动态类,该方法调用实际的TestMethodReal方法,实例化该类,然后调用该方法。
我错过了什么?
【问题讨论】:
-
这很奇怪
BindingFlags.Static | BindingFlags.NonPublic)!;。!是干什么用的?再次出现在您的错误Activator.CreateInstance(builder.CreateType()!)!;之前的行中 -
这是一个新的 C# 版本(我相信是 9.0 或 10.0)的一个有点烦人的特性。
GetMethod返回一个可为空的MethodInfo?类型(注意末尾的“?”)。!基本上保证了返回值不为空,否则我的 IDE 会报错并在它下面画一条难看的黄色波浪线。与CreateType和CreateInstance相同,分别返回可空的Type?和object?类型。 -
直接调用目标方法而不是请求虚拟调度:
generator.EmitCall(OpCodes.Call, method, Types.EmptyTypes)- 您不需要运行时为您解析TestMethodReal,因为您已经通过method准确引用了它:) -
您确定您在 .NET 6 / .NET Core 上运行吗,因为链接答案中使用的
AppDomain.DefineDynamicAssembly仅适用于 .NET Framework。 -
@GuruStron 我忘了提这个,但是那个方法的 .NET Core 替换是 AssemblyBuilder.DefineDynamicAssembly,我也在链接的
GetTypeBuilder方法中替换了它。
标签: c# .net-core reflection.emit .net-6.0