【问题标题】:Exception on receiving Assembly reference from another AppDomain从另一个 AppDomain 接收程序集引用时出现异常
【发布时间】:2013-01-02 14:49:22
【问题描述】:

我正在从新 AppDomain 中的特定“扩展”目录中加载所有 DLL,以从中获取一些与反射相关的信息。

这就是我正在尝试的:

我在我的解决方案中创建了一个新库 AssemblyProxy,它只有这个类:

public class AssemblyProxy : MarshalByRefObject
{
    public Assembly LoadFile( string assemblyPath )
    {
      try
      {
        return Assembly.LoadFile( assemblyPath );
      }
      catch
      {
        return null;
      }
    }
}

我确保此 DLL 存在于我的“扩展”目录中。然后我使用以下代码将所有程序集从“扩展”目录加载到新的AppDomain

foreach( string extensionFile in Directory.GetFiles( ExtensionsDirectory, "*.dll" ) )
{
        Type type = typeof( AssemblyProxy.AssemblyProxy );
        var value = (AssemblyProxy.AssemblyProxy) Domain.CreateInstanceAndUnwrap(
            type.Assembly.FullName,
            type.FullName );

        var extensionAssembly = value.LoadFile( extensionFile );

        types.AddRange( extensionAssembly.GetTypes() );
}

某些 DLL 确实可以成功加载,但在某些 DLL 上会抛出如下异常:

Could not load file or assembly 'Drivers, Version=2.3.0.77, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

编辑:新的 AppDomain 中不会引发异常。 DLL 在新的 AppDomain 中成功加载。一旦程序集引用返回到主/调用 AppDomain,就会引发异常。主/调用 AppDomain 是否尝试在收到引用时自行加载程序集?

谢谢。

【问题讨论】:

  • ReflectionLoadOnly 不足以满足您的(不为人知的)目的吗?
  • CreateInstanceAndUnwrap 有什么问题?
  • @ConradFrix ReflectionOnlyLoad 确实在当前 AppDomain 中加载程序集,而不是它的依赖项。据我所知,您无法从当前的AppDomain 卸载它们。
  • @ConradFrix:还有其他原因。就像只是扫描程序集或构建插件系统(在插件之后扫描程序集,如果没有则卸载它+卸载不再使用的插件)
  • @user1004959:因为你要返回Assembly。您将需要创建一个安全的可序列化/远程对象来传输该信息。一旦类型越界,你就完蛋了;p

标签: c# .net dll appdomain


【解决方案1】:

你不应该从新的AppDomain 返回一个Assembly 对象,因为这只有在你的主AppDomain 可以访问那些它没有的程序集时才有效,因为这些程序集位于以下目录中:

一种避免这种情况的方法是遵循 leppie 的评论和:

  1. 创建一个序列化类型,其中包含来自Assembly 对象所需的最少信息。
  2. 将此类型添加到两个 AppDomain 都可以访问的新程序集。最简单的方法是将其添加到 GAC。

另一种方法是使用Mono.Cecil 而不是System.Reflection。 Mono.Cecil 将允许您在不加载程序集的情况下检查它们。对于一个非常简单的示例,请查看此answer 的后半部分。

【讨论】:

  • 您确定Assembly 对象有问题吗?因为如果我使用ReflectionOnlyLoadFrom,那么相同Assembly 类型的对象引用将成功返回。
  • @user1004959 我很肯定返回一个 Assembly 对象不是你应该做的。也许特定程序集已加载到主 AppDomain。在 foreach 的最后一行添加断点,运行程序,然后使用 Visual Studio 的 QuickWatch 功能并评估 System.AppDomain.CurrentDomain.GetAssemblies()。如果您可以看到加载的程序集,那么它以某种方式加载到您的主 AppDomain。您是否在试验时订阅了 AssemblyResolve 事件?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-30
  • 1970-01-01
  • 2015-09-26
  • 1970-01-01
  • 2012-11-08
  • 1970-01-01
  • 2011-01-12
相关资源
最近更新 更多