.Net运行时从多个但相同的程序集实例化

时间:2014-02-25 09:47:13

标签: c# .net c++-cli

我目前正在努力在运行时从多个但相同的程序集中实例化一个类。这是我的设置:

  • 我有一个本机可执行文件,可以在运行时加载多个DLL。由于我的“目标DLL”是.Net程序集,我执行以下操作(对于每个目标DLL!):
    加载C ++ / CLI DLL(又名DynamicLoader)以获得本机和.Net世界之间的桥梁。之后,将创建目标DLL中的实际类的实例。

  • 为了能够在运行时卸载目标.Net DLL,我实现了一个基于http://www.codeproject.com/Articles/8832/Plug-in-Manager的类似插件的系统。
    它的简短摘要:DynamicLoader有两个类LocalLoaderRemoteLoader。在{root“AppDomain(在加载第一个C ++ / CLI DLL时创建)创建LocalLoader的实例。然后,此LocalLoader创建一个新的“目标AppDomain”并将RemoteLoader实例化到其中。然后,此RemoteLoader将加载目标程序集并实例化目标类。

  • 所以我有2个以上的AppDomains。一个AppDomain将由本机可执行文件自动创建,加载第一个C ++ / CLI DLL和每个“目标AppDomain”一个AppDomain。

  • 每个目标DLL都有自己的DynamicLoader程序集副本,每个目标DLL都将驻留在自己的目录中。

我当前的问题在于RemoteLoader被实例化的时候。首先,一些来源向您展示我正在做什么(没有捕获线):

void LocalLoader::InitializeRemoteLoader()
{
    // Load the RemoteLoader assembly (which is actually the current one)
    Assembly^ remoteLoaderAssembly = Assembly::GetAssembly(DynamicLoader::RemoteLoader::typeid);
    String^ remoteLoaderCodeBase = remoteLoaderAssembly->CodeBase;

    // Create new AppDomainSetup with appropriate name and base directory.
    AppDomainSetup^ appDomainSetup = gcnew AppDomainSetup();
    appDomainSetup->ApplicationName = m_targetAssemblyName + "_AppDomain";
    appDomainSetup->ApplicationBase = Path::GetDirectoryName(remoteLoaderAssembly->Location);
    appDomainSetup->PrivateBinPath = String::Empty;

    // Create AppDomain for RemoteLoader and target DLL
    try
    {
        m_targetAppDomain = AppDomain::CreateDomain(appDomainSetup->ApplicationName, nullptr, appDomainSetup);
    }
    catch (Exception^ e1)
    {
        // ERROR!
    }

    // Finally, create a new instance of the RemoteLoader and store the instance locally.
    if (m_targetAppDomain != nullptr)
    {
        try
        {
            Object^ newInstance = m_targetAppDomain->CreateInstanceFromAndUnwrap(
                remoteLoaderCodeBase,
                "DynamicLoader.RemoteLoader");

            if (newInstance != nullptr)
            {
                m_remoteLoader = (DynamicLoader::RemoteLoader^)(newInstance);
            }
        }
        catch (Exception^ e1)
        {
            // ERROR!
            Log4NetProvider::LocalLogger->Fatal("Could not type cast new instance of RemoteLoader to appropriate type!");
            Log4NetProvider::LocalLogger->FatalFormat("Created instance of type \"{0}\" from \"{1}\".", newInstance->GetType(), newInstance->GetType()->Assembly->CodeBase);
            Log4NetProvider::LocalLogger->FatalFormat("Tried to cast to type \"{0}\" from \"{1}\".", RemoteLoader::typeid, RemoteLoader::typeid->Assembly->CodeBase);

            Log4NetProvider::LocalLogger->FatalFormat(".NET Exception message: {0}", typeConvException->ToString());
        }
    }
}

问题发生在“最后一行”m_remoteLoader = (DynamicLoader::RemoteLoader^)(newInstance);DynamicLoader第一次正在开展工作,一切正常。第二次,类型转换失败

  

System.InvalidCastException:无法转换透明代理以键入“DynamicLoader.RemoteLoader”。

我试图分析哪些装配在什么时候实际使用并发现:

  • remoteLoaderCodeBase始终指向正确的程序集文件,因此每个“目标DLL”的程序集都在其自己的目录中。

  • newInstance->GetType()->Assembly->CodeBase指向第一个DynamicLoader大会。

  • RemoteLoader::typeid->Assembly->CodeBase指向当前的DynamicLoader汇编。

所以,长话短说:即使我明确告诉m_targetAppDomain->CreateInstanceFromAndUnwrap(...)从特定程序集实例化我的类,它将从根AppDomain中加载的第一个程序集创建实例!我究竟做错了什么?我想这应该以某种方式起作用,但我没有看到解决方案......

啊,最后一点:我正在使用.Net 4.0,所以如果还有更好的方法,请告诉我。 ;)

0 个答案:

没有答案