2

私は現在、MEF フレームワークを使用して実行時にプラグインをロードするプラグイン システムを備えたアプリケーション スイートを作成しています。

私は現在、最上位の WPF アプリケーションの 1 つをセットアップして、参照されている DLL を埋め込みリソースとして埋め込み、ここで説明する方法を使用して実行時にロードします。

これは正常に動作し、正常に動作する単一ファイル WPF アプリケーションを取得します。

ただし、別のトップ レベルのコンソール アプリケーションでは、MEF フレームワークを使用して実行時にプラグインをロードします (WPF アプリケーションは修正されており、明示的にプラグインが含まれています)。私のプラグインには、さまざまなライブラリに対するいくつかの依存関係があり、コンソール アプリケーションがプラグインをロードする拡張フォルダーには、さまざまなライブラリ dll がすべて散らばっています。

拡張機能ディレクトリに最上位の DLL ファイルのみが含まれるように、各プラグインの依存関係をそれ自体に埋め込みたいと考えています。上記で使用した方法は、これらの埋め込みリソースを検索するのは実行中のアセンブリのみであるため、プラグイン コンポーネントが必要な依存関係を見つけることができないため、このアプローチには対応していません。

現在の OnResolveAssembly メソッドは次のようになります。

public static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{
    Assembly executingAssembly = Assembly.GetExecutingAssembly();
    var assemblyName = new AssemblyName(args.Name);

    string path = assemblyName.Name + ".dll";
    if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false)
    {
        path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);
    }

    using (Stream stream = executingAssembly.GetManifestResourceStream(path))
    {
        if (stream == null)
            return null;

        var assemblyRawBytes = new byte[stream.Length];
        stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);

        return Assembly.Load(assemblyRawBytes);
    }
}

続行する最善の方法は、リストにロードされたすべてのアセンブリを追跡する機能を追加し、新しいアセンブリがこの方法でロードされたら、再帰的に同じことを行うことだと考えています。それらの中に埋め込まれた DLL をロードします。次に、これらの DLL をキャッシュとして機能するリストに追加できます。

これを進めるためのより良い方法はありますか?

4

1 に答える 1

2

私はあなたのものと非常によく似たソリューションを実装しましたが、それは私にとって非常にうまく機能します。ご覧のとおり、既に読み込まれているアセンブリを_referencesディクショナリに記録しています。

私の場合、埋め込まれたすべての依存関係を再帰的に「熱心に」読み込む必要はありませんが、埋め込まれたアセンブリはオンデマンドでアプリケーション ホストに登録されます。

public static class ApplicationHost
{
    private static readonly Dictionary<string, Assembly> _references = new Dictionary<string, Assembly>();

    [STAThread]
    private static void Main()
    {
        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => _references.ContainsKey(args.Name) ? _references[args.Name] : null;
        RegisterAssemblyAndEmbeddedDependencies();
        // continue application bootstrapping...
    }

    public static void RegisterAssemblyAndEmbeddedDependencies()
    {
        var assembly = Assembly.GetCallingAssembly();
        _references[assembly.FullName] = assembly;
        foreach (var resourceName in assembly.GetManifestResourceNames())
        {
            using (var resourceStream = assembly.GetManifestResourceStream(resourceName))
            {
                var rawAssembly = new byte[resourceStream.Length];
                resourceStream.Read(rawAssembly, 0, rawAssembly.Length);
                var reference = Assembly.Load(rawAssembly);
                _references[reference.FullName] = reference;
            }
        }
    }
}
于 2014-05-06T17:37:43.480 に答える