从另一个DLL引用一个DLL

13
我有一个C#应用程序,叫做App.exe。它引用了一个名为A.dll的DLL文件,而A.dll又引用了另一个DLL文件,即B.dll。但是它们的引用方式有所不同。在A.dll的代码中,它直接引用了B.dll(通过Project > References > Add B.dll)。然而,我的App.exe在运行时使用Assembly.Load()等代码加载A.dll。
因此,简单来说:

App.exe ----(运行时加载)---> A.dll ----(直接引用)---> B.dll

所有三个文件(App.exe、A.dll和B.dll)都驻留在同一个目录中,比如ExeDir。现在我想把A.dll和B.dll放在ExeDir的一个子目录中。我可以使用一个App.config文件指定A.dll的路径,并要求App.exe从该路径加载A.dll。到目前为止都很好。
然而问题是,当我这样做时,.NET会给我一个错误,说它无法找到与A.dll在同一目录中的B.dll。如果我将它移回原始目录(与App.exe在同一目录中),那么它就正常工作。这意味着,我可以把A.dll放在子目录中,但B.dll需要在原始目录中。
有没有办法让这两个DLL文件都保留在子目录中?
3个回答

12

在您的 app.config 文件中添加一个 <probing> 元素:

http://msdn.microsoft.com/zh-cn/library/823z9h8w.aspx

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

感谢D Stanley的回复。但是我有点不知所措。你能告诉我在这里具体要做什么吗?只是指定这个元素的程序集路径吗? - Sach
1
是相对于您的EXE程序文件。例如,在MSDN示例中,绑定器默认情况下会在BIN文件夹中搜索,但也会搜索bin2文件夹、bin2\subbin文件夹和bin3文件夹。将bin;bin2\subbin;bin3替换为A.dll和B.dll所在的文件夹(相对于EXE程序)。请注意,如果A.dll包含在探测路径中,则无需指定A.dll的路径。 - D Stanley
谢谢Stanley,我已经让它工作了! 不过这是我的错,我没有在这里解释完整的问题。我想要将DLLs放在不同的文件夹中的原因是我可能有几个不同的A.dll(内容不同),每个A.dll都可能引用B.dll。所以我想实现更安全的代码,这样如果不同的A.dll想要引用B.dll,也可以在其中变化。但看起来似乎做不到。还是谢谢!你回答了我的最初问题。 - Sach

9
你可以通过为当前AppDomain的AppDomain.AssemblyResolve事件提供事件处理程序来手动解决B.DLL程序集。
currentDomain.AssemblyResolve += ResolveLostAssemblies;

接下来提供一个ResolveEventHandler的实现:

private Assembly ResolveLostAssemblies(object sender, ResolveEventArgs args)
{
    // Find the assembly referenced by args.Name, load it dynamically, and return it.
}

我发现这种方法可以最好地控制程序集的加载顺序。特别是在应用程序是可插拔的情况下,每个插件都位于“plugins”文件夹的自己的子目录中(不一定是应用程序目录)。使用这种方法,技术上甚至不需要物理文件来表示程序集。尽管D Stanley's method通常被认为更标准。

1

GAC很糟糕 :) 不要使用它。 - Ignacio Soler Garcia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接