代码之家  ›  专栏  ›  技术社区  ›  Hershi

使用Assembly混合加载组件时的奇怪行为。LoadFrom和Assembly。负载

  •  5
  • Hershi  · 技术社区  · 17 年前

    使用混合加载组件时的奇怪行为 Assembly.LoadFrom 和 Assembly.Load :

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

    稍后,在我的测试代码中,当我尝试再次加载此程序集时 组装。负载 ,负载以 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. 你知道我该如何缓解这个问题吗?
    2 回复  |  直到 5 年前
        1
  •  9
  •   Tim Cooper    15 年前

    这并不奇怪。根据文档,使用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
  •  7
  •   Hershi    17 年前

    @肯特·布加特: 这似乎是正确的解释。为了获得完整的解释,Suzanne Cook发表了这篇博客文章,比你最初发布的文章稍微详细一些: http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx

    以下是利用AppDomain的代码。组装解析-

     // 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;
     }
    
    推荐文章