【问题标题】:Unexpected assembly conflict in other AppDomain其他 AppDomain 中的意外程序集冲突
【发布时间】:2013-09-18 12:30:19
【问题描述】:

我正在编写一个库,给定一个程序集,它会生成一个它的依赖程序集列表 - 包括依赖项的依赖项。 预期的使用场景主要包括托管代码 (.NET) 程序集。

我计算这个依赖列表的方法如下:

  • 创建一个临时 AppDomain (code)
  • 在该 AppDomain (code) 中创建帮助程序类的实例
  • 为我的初始程序集提供帮助:依赖树的根 (code)
  • 加载该程序集以在临时 AppDomain 的仅反射上下文 (code) 中进行检查
  • 递归处理依赖关系

请注意helper class 是在assembly 中定义的, 引用 .NET 程序集;没有其他的。 main library's assembly 确实引用了System.Reactive 程序集。

我希望临时 AppDomain 没有加载了这些 System.Reactive 程序集,但我收到了一个错误提示。

API restriction: The assembly 'file:///X:\some-path\System.Reactive.Linq.dll' has already loaded from a different location. It cannot be loaded from a new location within the same appdomain.
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.ReflectionOnlyLoadFrom(String assemblyFile)
   at DependencyResolver.AppDomainHelper.Util.AssemblyLoader.ReflectionOnlyLoadFromAssemblyPath(AssemblyName assembly, FileNotFoundException originalException) in DependencyResolver\DependencyResolver.AppDomainHelper\Util\AssemblyLoader.cs:line 96
   at DependencyResolver.AppDomainHelper.Util.AssemblyLoader.ReflectionOnlyLoad(AssemblyName assembly) in DependencyResolver\DependencyResolver.AppDomainHelper\Util\AssemblyLoader.cs:line 67
   at DependencyResolver.AppDomainHelper.Util.AssemblyLoader.ReflectionOnlyLoad(AssemblyName assembly)
   at DependencyResolver.Resolver.GetAllDependenciesRecursive(AssemblyName start, Func`2 filter, Func`2 preProcess, Action`1 postProcess) in DependencyResolver\DependencyResolver\Resolver.cs:line 39
   at DependencyResolver.Resolver.<>c__DisplayClass6.<GetAllDependenciesRecursive>b__5(AssemblyName an) in DependencyResolver\DependencyResolver\Resolver.cs:line 51
   at System.Reactive.Linq.Observαble.Select`2._.OnNext(TSource value)

当我在一堆包含不同版本的 System.Reactive.Linq.dll 的程序集上使用库时会发生这种情况。

如何确保我的临时 AppDomain 不会加载它不需要的任何内容?

【问题讨论】:

  • 创建自己的 DLL Hell 小角落是很有保证的。停止提供这么多帮助,只要确保探测路径设置正确即可。
  • 这没什么用。我需要一个这样的库用于另一个项目,在该项目中我只从大量 DLL 中传输必要的程序集(执行一个特定方法)。

标签: c# reflection assemblies appdomain conflicting-libraries


【解决方案1】:

一种方法是订阅AppDomainAssemblyResolve 事件并执行该方法?这样,当无法解析程序集时,将调用事件处理程序来加载程序集。这里唯一的问题是当您的程序集具有相同的文件名但不同的强名称时。

另一种方法是将所有程序集放在AppDomain 的基目录中,然后简单地调用该方法。然后检查AppDomain 上加载的程序集。这应该给你你正在寻找的列表,因为CLR 将延迟加载每个程序集。只要您有具有相同文件名但不同强名称的程序集,您就可以使用私有 bin 路径。

请注意,如果您有具有相同文件名的“弱命名”程序集,则会遇到问题。

【讨论】:

  • 我想你误解了我的问题。我可以毫无问题地找到可能相关的依赖 DLL。我的问题似乎是我创建的新 AppDomain 应该是空的(即它没有加载任何东西),但它似乎 确实 加载了一些程序集。
  • @derabbink 我明白了。会看看它,让你知道。你有重现这种情况的测试吗?顺便说一句,您的 GetAllTestDependencies 测试应该比较排序列表,并且您应该将 DependencyResolver.AppDomainHelper 添加到 expectedNames 列表中。
  • 我试图写一个test case,但它并没有重现我一开始遇到的异常。最初出现异常时的场景涉及大量专有代码,因此我无法在此处明确发布。我会继续寻找一个可复制的例子
猜你喜欢
  • 2016-04-16
  • 2013-07-20
  • 1970-01-01
  • 2013-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多