如何确定Assembly.Load()搜索程序集的位置?

7
我有一个使用BinaryFormatter反序列化对象的VS插件。为了解决这个对象的类型,它调用Assembly.Load(objectTypeFullName),但是触发了异常,因为Assembly.Load在搜索的任何位置都找不到该程序集。给定的程序集与插件程序集同级,但似乎Assembly.Load()无法在那里找到它。
一个可能的解决方案是确定Assembly.Load应该查找程序集的位置。
我该怎么办?
PS:我试图不将此程序集放在GAC上,因为我每次重新编译程序集都需要更新它。
3个回答

4

以下是代码片段,展示了如何使用AssemblyResolve来解决您的程序集问题(按照Reed Copey的答案):

// 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) {
    string desiredAssmebly = args.Name;
    if (desiredAssembly.Equals("NameUsedToLoadMyAssembly")){
        return Assembly.LoadFrom(myAssemblyPath);
    }

    return null;
  }

另外,请注意MSDN页面中关于AssemblyResolve的说明:

从 .NET Framework 4版本开始, ResolveEventArgs.RequestingAssembly属性返回请求装入程序集的装配程序集,后者无法解决加载问题...

如果您知道与请求程序集相关联的程序集位置,可以使用此功能。


Hershi,谢谢+1。事实上,你的解决方案最终是我使用的,并且我使用了你的代码片段。我将Reed的答案标记为已接受,因为它更完整。无论如何,还是非常感谢你。 - Andre Pena

4

谢谢Reed。一些注释:尽管AppDomain.AppendPrivatePath已被弃用,推荐使用AppDomainSetup.PrivateBinPath,但我只能使用第一个。在我修改后,AppDomainSetup.PrivateBinPath仍然为空。AppDomain.AppendPrivatePath允许我添加任何是AppDomain.BaseDirectory的子目录的路径,这在许多情况下已经足够了,但在我的情况下不行,因为我的BaseDirectory是DevEnv目录。另一个解决方案,AppDomain.AssemblyResolve已经足够好了。注意:只有当.NET无法自己解析程序集时,才会调用该事件。如果所有处理程序都返回null,则会抛出异常。 - Andre Pena

3
如果您只是想确定程序集加载器尝试从哪里加载您的dll,我建议您打开融合日志记录。这样做将使您能够获得输出,显示为相应的dll检查的每个路径。
有一个MSDN文章介绍如何配置融合日志记录,以及Suzanne Cook撰写的一篇有用的文章介绍如何调试加载失败。如果您打开LogFailures,则只会获取无法加载的程序集的输出。

这个融合日志非常有趣,我正在阅读这篇文章。谢谢。 - Andre Pena

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