【问题标题】:Weird behaviour when mixing loading of assemblies using Assembly.LoadFrom and Assembly.Load使用 Assembly.LoadFrom 和 Assembly.Load 混合加载程序集时的奇怪行为
【发布时间】:2009-01-06 13:17:28
【问题描述】:

使用Assembly.LoadFromAssembly.Load 混合加载程序集时的奇怪行为:

我在使用Assembly.LoadFrom 加载程序集以及稍后使用Assembly.Load 加载程序集时遇到了一个奇怪的行为。 我正在使用Assembly.LoadFrom 加载程序集,其中程序集位于一个文件夹中,该文件夹不是执行文件夹。

稍后在我的测试代码中,当我尝试使用 Assembly.Load 再次加载此程序集时,加载失败并显示 System.IO.FileNotFoundException(“无法加载文件或程序集...”),尽管程序集已经加载。使用强名称和非强名称加载都失败(再次加载此程序集的最初原因是使用 BinaryFormatter)。

但是,如果程序集位于执行文件夹中,则以后的加载在两种情况下都会成功,使用强名称和非强名称。在这种情况下,您可以看到从两个不同的位置加载了两个相同的程序集。

重现此问题的简单代码示例:

Assembly assembly1 = Assembly.LoadFrom(@"C:\a.dll");

// Loading with a strong-name fails
Assembly assembly2 = Assembly.Load(@"a, Version=1.0.0.0, Culture=neutral, PublicKeyToken=14986c3f172d1c2c");

// Also loading with a non-strong fails
Assembly assembly3 = Assembly.Load(@"a");
  1. 任何解释为什么 CLR 忽略已加载的程序集?
  2. 知道如何缓解这个问题吗?

【问题讨论】:

    标签: .net assemblies assembly.load


    【解决方案1】:

    这并不奇怪。根据文档,使用 Load 和 LoadFrom 加载会将程序集放置在不同的上下文中。 This 可能会有所帮助。

    1. 任何解释为什么 CLR 忽略已加载的程序集?

    因为他们处于不同的环境中。

    1. 知道如何缓解这个问题吗?

    从同一上下文加载,或帮助 CLR 找到程序集,可能通过将处理程序附加到 AppDomain.AssemblyResolve

    替代方案

    如果您从中加载程序集的位置是 AppDomain.BaseDirectory 下的子文件夹,您可以简单地在 App.config 中添加一个条目:

    <configuration>
       <runtime>
          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
             <probing privatePath="bin;bin2\subbin;bin3"/>
          </assemblyBinding>
       </runtime>
    </configuration>
    

    http://msdn.microsoft.com/en-us/library/823z9h8w.aspx

    【讨论】:

      【解决方案2】:

      @肯特·布加特: 这似乎是正确的解释。对于完整的解释,Suzanne Cook 有这篇博客文章,它比您发布的原始文章详细说明了一点: http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx

      以下是利用 AppDomain.AssemblyResolve 的代码 -

       // register to listen to all assembly resolving attempts:
       AppDomain currentDomain = AppDomain.CurrentDomain;
       currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
      
      
       // Check whether the desired assembly is already loaded
       private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args) {
          Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
          foreach (Assembly assembly in assemblies) {
             AssemblyName assemblyName = assembly.GetName();
             string desiredAssmebly = args.Name;
             if (assemblyName.FullName == desiredAssmebly) {
                 return assembly;
             }
          }
      
          // Failed to find the desired assembly
          return null;
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-26
        • 2011-12-08
        相关资源
        最近更新 更多