在运行时动态加载程序集依赖项的问题

时间:2009-02-26 22:11:13

标签: .net reflection assembly-resolution

让我试着解释一下我的问题。我目前正在尝试开发一个用.Net编写的小型“插件框架”(主要用于实验)。因此,我们的想法是通过在主应用程序的特定文件夹“插件”中部署dll来创建一个可以添加“插件”的主应用程序。 一切正常,插件正确实例化,但现在我遇到了问题。 我现在部署了一个使用其他第三方插件的插件“X”,所以现在我遇到的问题是在运行时找不到“X”所需的这些额外的第三方插件。因此,我的想法是现在添加一个额外的目录“dependencies”,我还部署了所有需要的插件。

所以我的第一个问题: 如何将程序集加载到应用程序域中(假设我知道它们的路径)s.t.它们可以被我的应用程序使用吗?

我尝试通过做类似的事情来解决这个问题:

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    //find the path to the assembly and then load and return it by
    //return Assembly.Load("pathToDependencies/failedAssembly.dll");
}

问题是这个事件处理程序现在被激活,在args变量中有“Presentation.Zune.dll”(我正在使用WPF应用程序)。好像那个程序集加载失败但实际问题是另一个dll。

有人可以建议我更好的方法来解决我的问题吗?我希望我能够充分解释我的情况,否则只是要求进一步澄清。

谢谢, 树里

3 个答案:

答案 0 :(得分:9)

您可以设置运行时的探测路径,以便它可以找到程序集。在应用配置文件中设置probing元素。

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="plugins;dependencies"/>
    </assemblyBinding>
  </runtime>
</configuration>

答案 1 :(得分:2)

The AssemblyResolve event happens when the framework tries to load an assembly, and fails.

这意味着如果它在args中给你Presentation.Zune.dll,框架就找不到那个程序集,这是你拦截它并做其他事情的机会,比如从目录加载它框架可能不知道 - 例如你的plugins \ dependencies文件夹......

离开我的头顶,我会尝试这样的事情:

Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    if( File.Exists(".\\Plugins\\"+args.Name) )  // it's a plugin
        return Assembly.Load(".\\Plugins\\"+args.Name);
    else if( File.Exists(".\\Plugins\\Dependencies\\"+args.Name) )  // it's a dependency OF a plugin
        return Assembly.Load(".\\Plugins\\Dependencies\\"+args.Name);
    else
        throw new Exception();
}

答案 2 :(得分:1)

BTW:如果缓存已在Dictionary中解析的程序集,则可以大大加快程序集的加载速度。如果A依赖于B,C和B依赖于C并且您加载A,则将为C调用AssemblyResolve两次,并且仅加载程序集一次更快:)

(我不确定是否总是会多次调用AssemblyResolve,但是在调试一次项目时我注意到了。并且缓存程序集并没有什么坏处。)