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

发布于 2024-07-14 02:32:16 字数 912 浏览 5 评论 0原文

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

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

我尝试通过执行以下操作来解决此问题:

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。

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

谢谢, 树里

let me try to explain my problem. I'm currently trying to develop a small "plugin-framework" written in .Net (mainly for experimenting a bit). So the idea is to have a main application to which "plugins" can be added by deploying dlls in a specific folder "plugins" of the main application.
Everything works fine, the plugins are instantiated properly, however now I'm facing a problem.
I have deployed now a plugin "X" that uses additional 3rd-party plugins and so now I have the problem that these additional 3rd-party plugins required by "X" are not found at run-time. My idea is therefore now to add an additional directory "dependencies" where I also deploy all of the needed plugins.

So my first question:
How can I load the assemblies into the application domain (given that I know the path to them) s.t. they can be used by my application?

I tried to approach that by doing something like:

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");
}

The problem is that this event-handler now gets activated having the "Presentation.Zune.dll" in the args variable (I'm using a WPF app). It seems as if that assembly failed loading but the actual problem is another dll.

Can someone suggest me a better way to solve my problem? I hope that I was able to explain my situation sufficiently, otherwise just ask for further clarification.

Thanks,
Juri

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

So要识趣 2024-07-21 02:32:16

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

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

You can set the probing path of the runtime so it can find the assemblies. Set the probing element in your apps config file.

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="plugins;dependencies"/>
    </assemblyBinding>
  </runtime>
</configuration>
聚集的泪 2024-07-21 02:32:16

当框架运行时,会发生 AssemblyResolve 事件尝试加载程序集,但失败了。

这意味着,如果它在参数中为您提供 Presentation.Zune.dll,则框架无法找到该程序集,并且这你有机会拦截它并做其他事情,比如从框架可能不知道的目录加载它 - 例如你的插件\依赖项文件夹......

在我的脑海中,我会尝试这样的事情:

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();
}

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

What this means is that if it's giving you Presentation.Zune.dll in the args, that the framework can't find that assembly, and this is your chance to intercept it and do other things, like load it from a directory that the framework might not know about - eg your plugins\dependencies folder...

Off the top of my head, I'd try something like this:

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();
}
埖埖迣鎅 2024-07-21 02:32:16

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

(我不确定是否总是这样调用AssemblyResolve不止一次,但我在调试项目时注意到了一次,而且缓存程序集也没有什么坏处......)

BTW: You can speed up loading assemblies considerably if you cache your assemblies that you already resolved in a Dictionary. If A depends on B, C and B depends on C and you load A, AssemblyResolve will be called twice for C, and loading the assembly only once is faster :)

(I am not sure if it is always the case that AssemblyResolve is called more than once, but I noticed it when debugging a project once. And it does not hurt to cache the assemblies...)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文