使用Activator.CreateInstance实例化Test类报MissingMethodException
反射实例化自定义类触发
MissingMethodException的排查与修复方案 问题核心根因
直接通过new关键字可以正常创建实例、但使用Activator.CreateInstance跨程序集反射时报找不到方法,本质不是Test类的构造函数不存在,而是CLR在反射做构造函数参数匹配时出现了类型身份偏差、访问权限不匹配的问题,常见触发场景:
- 最高发的触发原因是加载方式错误:
Assembly.LoadFile加载外部DLL时,会将目标DLL加载到完全独立的上下文,不会检查主程序中已经存在的同名称、同命名空间类型是否和目标DLL引用的是同一份。哪怕两个程序集中定义的CommonService代码完全一致,也会被CLR识别为两个完全不同的类型,传入的commonService实例和Test构造函数要求的类型不匹配,反射自然找不到符合签名的构造函数,抛出MissingMethodException。 - 构造函数的访问修饰符不符合反射跨程序集调用的权限要求,比如未显式标记
public的构造函数,跨程序集反射无法获取到对应元数据。 - Test类依赖的
BaseTest、CommonService等基础类型,在主程序和被加载的Test.dll中来自不同的程序集来源,反射加载类型时出现上下文错位,无法正确匹配构造函数签名。
可落地的修复步骤
- 替换DLL加载逻辑,对齐程序集加载上下文
放弃使用Assembly.LoadFile,改用Assembly.LoadFrom加载外部DLL。LoadFrom会自动将被加载DLL的依赖程序集搜索路径和当前主程序域对齐,只要主程序已经加载过和Test.dll引用同版本的共享依赖类型,就不会出现重复加载导致的类型身份分裂问题。
替换后的加载代码示例:// 替换原有Assembly.LoadFile的实现 var dll = Assembly.LoadFrom(@"xxx\Test.dll"); - 手动显式匹配构造函数,定位匹配偏差
不要依赖Activator.CreateInstance的隐式参数匹配逻辑,先通过反射显式获取目标构造函数,逐参数校验类型一致性,避免反射自动匹配的隐式偏差:// 显式获取匹配参数类型的公开实例构造函数 var targetConstructor = type.GetConstructor( bindingAttr: BindingFlags.Public | BindingFlags.Instance, binder: null, types: new[] { typeof(CommonService) }, modifiers: null ); // 若未匹配到目标构造函数,打印类的所有构造函数元数据辅助排查 if (targetConstructor == null) { var existingConstructors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance); throw new InvalidOperationException($"未找到接收{typeof(CommonService)}类型参数的公开构造函数"); } // 手动调用构造函数创建实例 dynamic c = targetConstructor.Invoke(new object[] { commonService }); - 统一共享类型的程序集来源
将CommonService、BaseTest、TestConfigurations这类跨项目共享的类型,抽到独立的公共类库项目中,主程序和Test.dll项目统一引用这个公共类库,不要在两个项目中各自定义同名同命名空间的类型,从根源上避免CLR将同名称类型识别为不同身份的问题。 - 校验构造函数的访问权限
确认Test类的构造函数显式标记为public,如果是访问级别受限的构造函数,需要在反射获取元数据时传入对应的BindingFlags权限标记,否则跨程序集反射无法读取到非公开的构造函数信息。
内容的提问来源于stack exchange,提问作者StayReal
相关产品推荐
相关产品推荐

