【问题标题】:Load assembly to temporary AppDomain将程序集加载到临时 AppDomain
【发布时间】:2017-02-28 13:36:38
【问题描述】:

我见过几个类似的问题,但没有一个能解决我的问题。场景是 - 我在外部存储中有几个 DLL,我需要获取有关它们的信息(具体而言,Assembly 版本和 AssemblyInformationalVersion)。我从以下代码开始:

List<byte[]> assemblies = _client.DownloadAllAssemblies();
foreach(var assemblyBytes in assemblies)
{
    var assembly = Assembly.ReflectionOnlyLoad(assemblyBytes);
    var assemblyName = assembly.GetName();
    ... // read version from assembly name
}

以上代码只能运行一次。如果我单击一个按钮来刷新视图 - 它会引发异常,说明程序集已加载并且无法重新加载它。然后我读到我应该创建临时域并将程序集加载到其中,这样我就可以在完成后卸载 AppDomain。我尝试了以下代码:

List<byte[]> assemblies = _client.DownloadAllAssemblies();
var tempDomain = AppDomain.Create("TemporaryDomain");
foreach(var assemblyBytes in assemblies)
{
    var assembly = tempDomain.Load(assemblyBytes);
    var assemblyName = assembly.GetName();
    ... // read version from assembly name
}
AppDomain.Unload(tempDomain);

以上代码抛出 FileNotFound 异常,提示“无法加载文件或程序集...”

我明白为什么会这样,但我不知道如何解决这个问题。这项任务似乎很琐碎:

  1. 加载文件,
  2. 阅读其版本,
  3. 算了。

上述逻辑没有什么复杂的。运行时要求似乎过于复杂。有谁知道我怎样才能让它工作?

【问题讨论】:

  • 需要更多的堆栈跟踪(始终提供完整的信息),在完成加载您传入的任何字节数组之前,可能无法加载依赖程序集。AppDomain 上有一些属性您应该从默认值复制,例如探测路径。此外,您仍然想使用ReflectionOnlyLoad 它不会尝试解决所有问题。
  • @escape-llc AppDomain 不公开“ReflectionOnlyLoad”功能。稍后我将使用 StackTrace 更新问题。谢谢。

标签: c# .net .net-assembly appdomain


【解决方案1】:

任务并不像看起来那么简单。 AppDomain.Load 方法不打算以这种方式使用它。

System.AppDomain 类的Load 方法可以加载程序集,但主要用于 COM 互操作性。它不应用于将程序集加载到调用它的应用程序域以外的应用程序域中。

我看到您的情况有两种解决方案:

  1. 简单的方法。将汇编字节数组写入临时文件,并通过FileVersionInfo.GetVersionInfo 读取其FileVersionProductVersion。大多数情况下,这些值应与AssemblyVersionAssemblyInformalVersion 中的值相同。

  2. 使用AppDomain 的正确方法。应用程序域的问题在于,您要加载的程序集应该从该域内部而不是外部加载。

要实现这一点,您需要创建包含所有必要逻辑的特殊类,并且该类应通过引用编组(从MarshalByRef 类继承)。

然后,在创建新域之后,您应该在新创建的域中加载该类并解包它。您可以使用CreateInstanceAndUnwrap 方法来做到这一点。

此类将存在于另一个域中,对其方法和属性的所有调用都将编组到该域,因此您可以使用您的逻辑来加载程序集并读取必要的信息。或者在其他域内做任何其他事情。

完成后,您可以并且应该卸载该域。

不要忘记,最初的应用程序域是完全空的,因此当您创建任何类的实例或加载其他程序集时,.net 应该解析并将所有相关程序集加载到该域中。有时系统无法自动执行此操作,但在这种情况下,您可以通过订阅新域的AssemblyResolve 事件来帮助系统执行此操作。

【讨论】:

  • 感谢您的回复。如果“AppDomain.Load 方法不打算以这种方式使用它。”那么我不想“滥用”它。我将尝试临时下载解决方案并让您知道是否成功。我可以控制 dll 的创建(它们是在网站上创建和编译的)所以我应该能够设置 FileVerison 使其等于 AssemblyVersion。
  • 我最终得到了 steve16351 的解决方案 stackoverflow.com/questions/26106431/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多