1

System.Reflection.Assembly.LoadFileを使用して、実行時にいくつかのプラグイン (任意の .NET 言語で実装) をロードする Managed C++ で DLL を開発しました。すべてのプラグインで実装されるインターフェースは 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ファイルが Managed 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 に答える