System.Type的C#反序列化为加载的程序集中的类型抛出

我有一个运行正常的应用程序a.exe并加载了一个程序集b.dll,如果重要的话,这是一个Prism模块.此dll是从不在路​​径中但位于a.exe所在目录中的目录加载的.

装配由Prism完成,设置如下:

public class MyModuleCatalog : ComposablePartCatalog
{
  private readonly AggregateCatalog _catalog;

  public MyModuleCatalog()
  {
      //directory Modules is not in the path,but all
      //dependencies of b.dll are,so b.dll gets loaded fine
    var asmCat = new AssemblyCatalog( "Modules/b.dll" );
    _catalog.Catalogs.Add( asmCat );
  }

  public override IQueryable<ComposablePartDeFinition> Parts
  {
    get { return _catalog.Parts; }
  }
}

class BootStrapper : MefBootstrapper
{
  ....
  protected override void ConfigureAggregateCatalog()
  {
    base.ConfigureAggregateCatalog();

    AggregateCatalog.Catalogs.Add( new AssemblyCatalog( Assembly.GetExecutingAssembly() ) );
    AggregateCatalog.Catalogs.Add( new MyModuleCatalog() );
  }
  ....
}

在b.dll中有一个类ImInB:

[Export]
public class ImInB
{
  public void DoIt()
  {
    try
    {
      var stream = new MemoryStream();
      //using System.Runtime.Serialization.Formatters.
      var formatter = new BinaryBinaryFormatter();

        //serialize our type
      formatter.Serialize( stream,this.GetType() );

        //get it back
      stream.Position = 0;
      var obj = formatter.Deserialize( stream ); //this throws??
    }
    catch( Exception e )
    {
    }
  }
}

这只是示例代码,是加载/保存设置到数据库的持久框架的一部分.对象的类型始终是序列化的,并且充当数据库的键.在反序列化时,将对类型作为对要加载的对象的双重检查进行检索.
函数从a.exe调用

container.GetExportedValue<ImInB>().DoIt();

反序列化类型时抛出的异常(之前已成功序列化两行)是:

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

问题:

>这怎么可能?函数从dll中调用,但是说它找不到那个dll.
>我该如何解决这个问题?我怎么告诉Deserialize嘿,dll已经加载了,不去寻找它

UPDATE
我的第二个问题基本上由Felix K回答;以下代码修复了该问题:

public static class AssemblyResolverFix
{
  //Looks up the assembly in the set of currently loaded assemblies,//and returns it if the name matches. Else returns null.
  public static Assembly HandleAssemblyResolve( object sender,ResolveEventArgs args )
  {
    foreach( var ass in AppDomain.CurrentDomain.GetAssemblies() )
      if( ass.FullName == args.Name )
        return ass;
    return null;
  }
}

//in main
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolverFix.HandleAssemblyResolve;

这也证明了程序集是有效加载的,包括它的所有依赖项,所以第一个问题仍然存在:对我来说,为什么框架本身无法解决这个问题,这是一种谜.此外,我无法在使用大致相同结构的第二个应用程序中重现它.

解决方法

我不知道为什么在dll已经加载时会发生这种情况,但我认为这与序列化本身无关,对我来说它看起来像是一个.NET错误.

这可能会帮助你,或指出你正确的方向:

AppDomain current = AppDomain.CurrentDomain;
current.AssemblyResolve += new ResolveEventHandler(HandleAssemblyResolve);

static Assembly HandleAssemblyResolve(object sender,ResolveEventArgs args)
{
    /* Load the assembly specified in 'args' here and return it,if the assembly is already loaded you can return it here */
}

每当缺少一个DLL时,都会调用resolve方法,因此当你的dll丢失时也会发生这种情况. dotNET无法找到它,因为它位于“Modules”文件夹中,因此您必须自己解析引用.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...