Загрузка взаимозависимых сборок из C ++ / CLI

Я хочу загрузить две сборки из C ++ / CLI; сборка A зависит от сборки B, и обе являются проектами VB.Net (3.5). Я хочу, чтобы они загружались из байтового массива, поэтому я использую Assembly :: Load (), но когда я пытаюсь создать экземпляр класса из сборки A, фреймворк игнорирует ранее загруженную сборку B и пытается загрузить ее снова, что не удается, потому что его нет в пути поиска. «Имя» сборки такое же, поэтому я не знаю, почему она не работает. В целях тестирования моя программа загружает байты прямо из скомпилированного изображения, но реальный код будет загружаться иначе. Это мой тестовый код:

#include "stdafx.h"

using namespace System;
using namespace System::Windows::Forms;
using namespace System::IO;
using namespace System::Reflection;

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    array<unsigned char>^   bytes;
    FileStream^     f;

    f = gcnew FileStream(L"c:\\...\\AssemblyB.dll", FileMode::Open);
    bytes = gcnew array<unsigned char>((int)f->Length);
    f->Read( bytes, 0, (int) f->Length );
    f->Close();
    f = nullptr;
    Assembly^   assemblyb = Assembly::Load(bytes);

    f = gcnew FileStream(L"c:\\...\\AssemblyA.dll", FileMode::Open);
    bytes = gcnew array<unsigned char>((int)f->Length);
    f->Read( bytes, 0, (int) f->Length );
    f->Close();
    f = nullptr;
    Assembly^   assemblya = Assembly::Load(bytes);

    bytes = nullptr;

    // Here I get the file not found exception!
    Object^     mf = assemblya->CreateInstance(L"AssemblyA.MainForm");

    // This line is not reached unless I copy assemblyb.dll to my app's folder:
    mf->GetType()->InvokeMember(L"ShowDialog",BindingFlags::Default | BindingFlags::InvokeMethod,
                                mf->GetType()->DefaultBinder, mf, nullptr );

    return 0;
}

Ошибка:

Не удалось загрузить файл или сборку AssemblyB, Version = 1.0.3650.39903, Culture = нейтральный, PublicKeyToken = null или одну из их зависимостей. Системе не удается найти указанный файл.

Когда я проверяю assemblyb-> FullName, он говорит именно «AssemblyB, Version = 1.0.3650.39903, Culture = нейтральный, PublicKeyToken = null».

Конечно, если я скопирую AssemblyB.dll в папку моей тестовой программы, код будет работать нормально, но это не то, что я хочу.

Любые идеи?

(Кстати, моим вторым шагом будет попытка заставить AssemblyA использовать классы, которые мой C ++ / CLI exe будет выставлять.)


person Guillermo Prandi    schedule 30.12.2009    source источник
comment
Мммм ... из того, что я здесь прочитал (stackoverflow.com/questions/416468/) кажется, я должен реализовать ResolveHandler, но я не имею ни малейшего представления о какой синтаксис для AddHandler () в C ++ / CLI! :П   -  person Guillermo Prandi    schedule 30.12.2009


Ответы (1)


Хорошо, я просто смутился. Это все в документации.

// This class is just for holding a managed static variable for assemblyB
ref class Resolver {
public:
    static  Assembly^   assemblyB;
};

// This is the delegate for resolving assemblies
Assembly^ ResolveHandler(Object^ Sender, ResolveEventArgs^ args)
{
    // Warning: this should check the args for the assembly name!
    return Resolver::assemblyB;
}
.
.
.
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
    // Set up the handler for the AssemblyResolve event
    AppDomain::CurrentDomain->AssemblyResolve += gcnew ResolveEventHandler( ResolveHandler );
.
.
.
    // Load assemblyb into the static variable available to the resolver delegate
    Resolver::assemblyb = Assembly::Load(bytes);
.
.
.

Надеюсь, кому-то это пригодится. :)

person Guillermo Prandi    schedule 30.12.2009