2

我想从 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=neutral、PublicKeyToken=null ”或其依赖项之一。该系统找不到指定的文件。

当我检查 assemblyb->FullName 时,它​​准确地说是“ AssemblyB, Version=1.0.3650.39903, Culture=neutral, PublicKeyToken=null ”。

当然,如果我将 AssemblyB.dll 复制到我的测试程序的文件夹中,代码就可以正常工作,但这不是我想要的。

有任何想法吗?

(顺便说一句,我的第二步是尝试让 AssemblyA 使用我的 C++/CLI exe 将公开的类。)

4

1 回答 1

9

好吧,我只是让自己尴尬。这一切都在文档中。

// 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);
.
.
.

我希望有人觉得这很有用。:)

于 2009-12-30T02:39:51.627 回答