【发布时间】:2012-09-19 19:21:35
【问题描述】:
是否可以阻止加载工作目录中的 dll 并强制它在我指定的其他地方使用 dll?
我正在尝试运行一些单元测试并收到此 InvalidCast 异常:
[A]AssemblyA.DataType 不能转换为 [B]AssemblyA.DataType。 A型 源自'AssemblyA,版本=1.0.4645.21698,文化=中性, PublicKeyToken=null' 在上下文 'LoadFrom' 的位置 'E:\webservice\bin\AssemblyA\AssemblyA.dll'。 B型起源于 'AssemblyA,版本=1.0.4645.21698,文化=中性, PublicKeyToken=null' 在上下文“默认”的位置 'E:\TestResults\Out\AssemblyA.dll'。
在测试启动时,它会调用一些初始化代码,这些代码使用 Assembly.LoadFrom 从 E:\webservice\bin\AssemblyA\AssemblyA.dll 加载 dll 并创建一些类型并将它们放入缓存中。
存在将 dll 复制到该位置的构建后事件,因此它们在两个位置都是完全相同的 dll。
但是单元测试是从 E:\testresults\out\ 的工作目录运行的,所以它会自动在那里加载 AssemblyA.dll,忽略已经加载的程序集,而没有给我机会用 Appdomain 拦截该加载.AssemblyResolve 事件
因此,当单元测试代码尝试从 E:\webservice\bin\AssemblyA\AssemblyA.dll 中的缓存中检索对象时,它会说无效转换,因为它期望来自 E:\TestResults\ 的类型输出\AssemblyA.dll
查看Best Practices for Assembly Loading 后,似乎没有办法阻止它从工作目录加载 dll,即使我已经手动加载了我想要使用的 dll。除了将应用程序更改为根本不从 E:\webservice\bin... 加载之外,还有其他选择吗?
(使用 LoadFile 或 Load byte[] 也会导致同样的错误)
【问题讨论】:
-
我不明白您为什么引用程序集,这不正确?顺便说一句:你不能关闭CLR的默认加载行为。
-
这只是系统现有的架构,它是这样设置的,以允许加载不同子文件夹中的不同版本的弱命名dll。可能有更好的方法可以实现相同的结果,但我现在仍然坚持。它以前没有任何单元测试,所以这从来不是问题。
-
我建议编写不同的单元测试。
test projectA正在引用assemblyA并对其进行测试。另一个test projectB正在引用和测试assemblyB。这是一个想法吗? -
问题在于,AssemblyA和AssemblyB都引用了共享代码,该共享代码是从另一个位置执行dll的LoadFrom而不是使用工作目录中的dll
-
System.AddIn 处理此问题的方式是在引用程序集上禁止 CopyLocal=true。这种方式仅通过调用 LoadFrom 而不是由 CLR 程序集加载器加载。
标签: c# .net assemblies appdomain