如何阻止MissingMethodException中断程序后续执行?
问题背景
我为学生提供一个DLL文件框架,要求他们用.NET C#填充其中方法。学生将编译后的DLL放入我的「进度检测」应用,该应用会检查方法完成情况并给出完成百分比。
应用中针对每个可能缺失或损坏的内容,我使用try/catch块处理:执行成功则向布尔列表添加true,捕获错误或未满足条件则添加false,代码如下:
List<bool> testResults; testResults = new List<bool>(); Print("Starting Engine Tools testing."); try { EngineTools.Print("Testing Print"); testResults.Add(true); } catch (Exception ex) { Print("Print Method in EngineTools Failed"); testResults.Add(false); }
正常使用合规DLL时程序运行正常,但替换为移除所有内容的测试用坏DLL后,调用EngineTools.Print(object message)时抛出:
"Unhandled Exception: System.MissingMethodException: Method not found: 'Void GameEngine.EngineTools.Print(System.Object)'."
该异常未被try/catch捕获,导致程序终止,无法执行后续测试,也不显示最终得分。
核心原因
MissingMethodException是在JIT(即时编译)阶段抛出的,而非方法执行阶段。你的try/catch块只能捕获方法调用执行过程中产生的异常,但当CLR尝试编译包含EngineTools.Print调用的代码段时,发现找不到目标方法,会直接抛出该异常——此时代码还未进入try块的执行逻辑,自然无法被捕获。
解决方法
1. 使用反射动态调用方法
通过反射在运行时动态查找并调用目标方法,将方法查找的过程纳入try/catch块,从而捕获MissingMethodException:
try { Type engineToolsType = typeof(EngineTools); // 匹配方法名和参数类型 MethodInfo printMethod = engineToolsType.GetMethod("Print", new Type[] { typeof(object) }); if (printMethod != null) { // 静态方法传入null作为实例参数 printMethod.Invoke(null, new object[] { "Testing Print" }); testResults.Add(true); } else { Print("Print Method in EngineTools not found"); testResults.Add(false); } } catch (Exception ex) { Print($"Print Method in EngineTools Failed: {ex.Message}"); testResults.Add(false); }
反射会在运行时动态检查方法是否存在,所有相关异常都能被try/catch捕获,不会导致程序终止。
2. 基于抽象接口实现晚绑定
定义一个抽象接口(如IEngineTools),让学生的DLL实现该接口,检测程序通过接口调用方法,并使用Assembly.Load动态加载DLL创建实例:
// 定义接口 public interface IEngineTools { void Print(object message); } // 检测程序中的调用逻辑 try { // 动态加载学生的DLL Assembly studentAssembly = Assembly.LoadFrom("StudentEngine.dll"); Type engineToolsType = studentAssembly.GetType("GameEngine.EngineTools"); if (typeof(IEngineTools).IsAssignableFrom(engineToolsType)) { IEngineTools engineTools = (IEngineTools)Activator.CreateInstance(engineToolsType); engineTools.Print("Testing Print"); testResults.Add(true); } else { Print("EngineTools does not implement IEngineTools"); testResults.Add(false); } } catch (Exception ex) { Print($"Print Method in EngineTools Failed: {ex.Message}"); testResults.Add(false); }
这种方式遵循依赖倒置原则,避免了编译时对具体实现的依赖,所有加载和调用异常都能被捕获。
补充提示
- 除
MissingMethodException外,TypeLoadException、MissingFieldException等也属于JIT阶段抛出的异常,常规try/catch无法捕获,需用反射或接口晚绑定处理。 - 使用反射时需严格匹配方法名和参数类型,避免因参数不一致引发
AmbiguousMatchException。
内容的提问来源于stack exchange,提问作者Fr0z3n5un

