加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 07:56:02 所属栏目:百科 来源:网络整理
导读:我有一个运行正常的应用程序a.exe并加载了一个程序集b.dll,如果重要的话,这是一个Prism模块.此dll是从不在路??径中但位于a.exe所在目录中的目录加载的. 装配由Prism完成,设置如下: public class MyModuleCatalog : ComposablePartCatalog{ private readonly
我有一个运行正常的应用程序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”文件夹中,因此您必须自己解析引用.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读