1

我在托管 C++ 中开发了一个 DLL,它在运行时使用System.Reflection.Assembly.LoadFile加载一些插件(以任何 .NET 语言实现)。所有插件实现的接口都是用C#实现的。托管 C++ 代码使用它,如下所示:

#using <IMyPluginInterface.dll>  // Make the 'IMyPluginInterface' type available

ref class PluginManager {
    List<IMyPluginInterface ^> ^m_plugins;

    // Load all plugins in a well-known directory.
    void load() {
        for ( string dllFile in Directory.GetFiles( .., "*.dll" ) ) {
            // Lookup the type of the plugin object using Reflection
            Type pluginType = ...;

            // Finally, instantiate the plugin and add it to our list.
            m_plugins.Add( (IMyPluginInterface ^)Activator.CreateInstance( pluginType ) );
        }
    }
}

加载插件效果很好;我面临的问题是,在运行时,该IMyPlugnInterface.dll文件可能与托管 C++ DLL 不在同一目录中。这意味着“IMyPluginInterface”类型在运行时不可用,并引发异常。

我之前问过是否有可能影响解析通过#using语句引用的 DLL 时使用的查找路径。不幸的是,这并没有产生任何结果。

可能有不同的方法吗?可以将通过引用的类型#using编译到托管 C++ DLL 中吗?也许其他人有完全不同的解决方案?

4

2 回答 2

4

您可以使用多个选项 - 如果您事先知道程序集的位置,您可以将该路径添加到应用程序的配置文件中:

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="MyPath"/>
    </assemblyBinding>
  </runtime>
</configuration>

如果要在运行时搜索程序集,可以实现AppDomain::CurrentDomain->AssemblyResolve事件处理程序:

ref class AssemblyResolver
{
public:
    /// The path where the assemblies are searched
    property String^ Path
    {
        String^ get()
        { return path_; }
    }

    explicit AssemblyResolver(String^ path)
        : path_(path)
    { /* Void */ }

    Assembly^ ResolveHandler(Object^ sender, ResolveEventArgs^ args)    
    {
        // The name passed here contains other information as well
        String^ dll_name = args->Name->Substring(0, args->Name->IndexOf(','));
        String^ path = System::IO::Path::Combine(path_, dll_name+".dll");

        if ( File::Exists(path) )
            return Assembly::LoadFile(path);

        return nullptr;
    }

private:
    String^ path_;
};

您可以使用以下方式连接它:

AssemblyResolver^ resolver = gcnew AssemblyResolver(path);
AppDomain::CurrentDomain->AssemblyResolve += gcnew ResolveEventHandler(
    resolver, 
    &AssemblyResolver::ResolveHandler
);

只需确保在调用任何可能使用必须解析的程序集中类型的方法之前完成此操作。

于 2009-10-06T10:23:52.513 回答
1

这不是标准的.net 程序集解析策略吗?详细介绍请看这里

于 2009-10-01T11:09:19.553 回答