第三方DLL属性存在性检查通过后访问仍报方法未找到异常排查
问题分析与解决方案
这种情况我之前也碰到过,大概率是程序集版本不匹配在搞鬼,给你拆解下核心原因和解决办法:
为什么会出现这种矛盾?
你用type.GetProperty("EnsureTextField")检查时返回非空,说明当前进程里加载的Account类型确实有这个属性;但直接访问am.account.EnsureTextField却抛出找不到get方法的异常,核心问题出在编译时引用的DLL和运行时实际加载的DLL不一致:
- 编译你的项目时,你引用的
Shared.Models.dll里Account类确实有EnsureTextField属性;但程序运行时,加载的却是另一个版本的Shared.Models.dll——这个版本里要么该属性的get方法签名被修改了(比如返回值类型变了),要么属性直接被移除了。 - 极端情况是进程里加载了多个版本的
Shared.Models.dll,反射检查的是其中一个版本的类型,而你的am.account实例来自另一个版本的类型。
具体排查&解决步骤
- 先核对运行时DLL版本:找到程序运行目录下的
Shared.Models.dll,右键→属性→详细信息,看看版本号和你项目引用的DLL版本是否一致。如果不一样,把编译时用的那个版本替换到运行目录里。 - 绑定重定向(.NET Framework项目适用):如果你的项目依赖多个第三方库,它们各自引用了不同版本的
Shared.Models.dll,可以在app.config/web.config里加绑定重定向,强制所有组件用同一个版本:
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Shared.Models" publicKeyToken="你的DLL公钥令牌" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-你要替换的最高版本" newVersion="统一使用的版本号" /> </dependentAssembly> </assemblyBinding> </runtime>
- 改用反射访问属性(最稳妥的兼容性方案):既然你已经用反射做了存在性检查,不如直接用反射获取属性值,绕开编译时硬编码带来的版本问题:
var type = am.account.GetType(); var ensureTextFieldProp = type.GetProperty("EnsureTextField"); if (ensureTextFieldProp != null) { cbEnsureTextField.Checked = (bool)ensureTextFieldProp.GetValue(am.account); }
这样只要属性名称不变,不管运行时的get方法细节有没有变化,都能正常拿到值,完美适配向后兼容的需求。
- 检查强名称冲突:如果你的
Shared.Models.dll是强名称签名的,哪怕文件名一样,版本号或公钥令牌不同,CLR都会把它们当成完全不同的程序集。要确保所有引用该DLL的地方,都用同一个强名称版本的文件。
内容的提问来源于stack exchange,提问作者xoail
相关产品推荐
相关产品推荐

