C # десериализация System.Type выбрасывает тип из загруженной сборки

У меня есть приложение 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 уже загружена, не ищите ее

ОБНОВЛЕНИЕ на мой второй вопрос в основном отвечает Феликс К. следующий код устраняет проблему:

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;

Это также доказывает, что сборка эффективно загружена, включая все ее зависимости, поэтому остается первый вопрос: для меня загадка, почему фреймворк не может понять это самостоятельно. Более того, я не могу воспроизвести его во втором приложении, использующем примерно такую ​​же структуру.

7
задан stijn 31 December 2011 в 17:11
поделиться