Pythonnet通过System.Reflection.Assembly.LoadFrom加载同名不同版本DLL时依赖加载异常问题
Pythonnet通过System.Reflection.Assembly.LoadFrom加载同名不同版本DLL时依赖加载异常问题
看起来你踩中了CLR程序集加载机制里一个挺常见的坑,我来给你把问题拆解得明明白白:
为什么Dependency 2压根没被加载?
这本质是CLR对强名称程序集的加载策略在起作用:
- 你的两个Dependency DLL是同名且带相同公钥的强名称程序集,CLR对这类程序集的识别逻辑是:程序集名称 + 公钥令牌才是它的核心标识,版本号在默认绑定策略下会被“忽略”——准确来说,一旦某个符合「名称+公钥」标识的程序集被加载到应用域,后续任何请求加载同标识不同版本的程序集时,CLR都会直接返回已经加载的那个实例,不会再去查找或加载新的版本。
- 当你先加载Assembly V1时,Dependency V1被加载到应用域并进入缓存。之后加载Assembly V2时,CLR解析它的依赖时,发现缓存里已经有匹配的Dependency条目,就直接复用了V1,根本不会尝试去查找和加载Dependency V2。
为什么调用LoadFrom时没抛出异常?
这是因为CLR采用了**延迟加载(懒加载)**的机制:
- 你调用
System.Reflection.Assembly.LoadFrom加载Assembly V2的时候,CLR只会把Assembly V2本身加载到内存中,不会立刻去解析并加载它的所有依赖项。只有当你真正执行Assembly V2中用到Dependency的代码片段时(也就是JIT编译这段代码的阶段),CLR才会触发依赖加载的逻辑。 - 所以在LoadFrom执行的阶段,CLR根本没碰Dependency相关的解析逻辑,自然不会抛出异常。直到你运行Assembly V2里的代码,调用到和Dependency V1不兼容的部分时,才会触发运行时异常。
可选的解决方向
如果你确实需要在同一个应用中使用两个版本的程序集,可以试试这两种方案:
- 应用程序域隔离:为每个版本的Assembly创建独立的应用程序域,每个应用域的程序集缓存是完全独立的,这样两个版本的Dependency就能各自被加载,互不干扰。
- 自定义程序集解析逻辑:订阅应用域的
AssemblyResolve事件,当CLR尝试加载Dependency时,手动指定对应版本的DLL路径,绕过默认的缓存匹配逻辑。
内容来源于stack exchange
相关产品推荐
相关产品推荐

