Как изменить путь поиска для библиотек .NET, на которые ссылаются через #using в Managed C ++? - PullRequest
1 голос
/ 01 октября 2009

Я разработал DLL в Managed C ++, которая загружает некоторые плагины (реализованные на любом языке .NET) во время выполнения, используя System.Reflection.Assembly.LoadFile . Интерфейс, который реализован всеми плагинами, реализован на C #. Он используется кодом Managed 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 недоступен во время выполнения, и генерируется исключение.

Ранее я спрашивал, возможно ли повлиять на путь поиска, используемый при разрешении библиотек DLL, на которые ссылается оператор #using. К сожалению, это не дало никакого результата.

Может быть, есть другой подход к этому? Можно ли скомпилировать типы, на которые ссылается #using, в управляемую C ++ DLL? Может быть, у кого-то есть другое решение?

Ответы [ 2 ]

4 голосов
/ 06 октября 2009

Вы можете использовать несколько опций - если вы заранее знаете, где будет расположена сборка, вы можете добавить этот путь в файл конфигурации вашего приложения:

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

Просто убедитесь, что это сделано перед вызовом любых методов, которые могут использовать типы из сборки, которая должна быть разрешена.

1 голос
/ 01 октября 2009

Разве это не стандартная стратегия разрешения сборки .net? Подробнее см. здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...