LoginSignup
3
2

More than 1 year has passed since last update.

C# .NET6 DLL 動的ロードについて

Posted at

#C# WPF .NET6 DLL 動的ロードについての調査事項

#AssemblyロードにてDLLを読み込む

#問題点 
動的DLLをアプリケーション起動中に再ロードしてもオブジェクトが解放されな

#解決案
 ##AppDomainを使用しての解放
マイクロソフトのリファレンスから「.NET で使用できない.NET Framework テクノロジー」を参照 .NET は使用できない事が判明

 ##AssemblyLoadContextを使用しての解放
参考 URL https://www.ayumax.net/entry/2019/12/10/000000/
http://crocell01.blog18.fc2.com/blog-entry-173.html
https://learn.microsoft.com/ja-jp/dotnet/core/tutorials/creating-app-with-plugin-support

#コード

    public class manage
    {
        static List<sampleInterface> CommadList;

        public void LoadUnLoad()
        {
            string currentpath = System.IO.Directory.GetCurrentDirectory();

            //CommadList = new List<sampleInterface>();

            // プラグインパスチェック
            if (currentpath != null && System.IO.Directory.Exists(currentpath))
            {

                // ディレクトリ内のDLLファイルパスを取得
                foreach (string dll in Directory.GetFiles(currentpath, "ClassLibrary*.dll"))
                {
                    ExecuteAndUnload(dll, out WeakReference alcWeakRef);

                    // アンロードされるまで待つ
                    int counter = 0;
                    for (counter = 0; alcWeakRef.IsAlive && (counter < 10); counter++)
                    {
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                    }

                    if (counter < 10)
                    {
                        System.Diagnostics.Debug.WriteLine("アンロード成功");
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("アンロード失敗");
                    }
                }
            }


        }


        [MethodImpl(MethodImplOptions.NoInlining)]
        void ExecuteAndUnload(string assemblyPath, out WeakReference alcWeakRef)
        {
            // アセンブリをロードするAssemblyLoadContextを作成
            var alc = new TestAssemblyLoadContext();

            // アセンブリをロード
            Assembly a = alc.LoadFromAssemblyPath(assemblyPath);

            // 外からアンロードを検知するために弱参照を設定
            alcWeakRef = new WeakReference(alc, trackResurrection: true);

            // リフレクションで関数コール


            foreach (Type type in a.GetTypes())
            {
                // リフレクションで関数コール
                Type t = type.GetInterfaces().FirstOrDefault((_t) => _t == typeof(sampleInterface));

                if (t == default(sampleInterface)) continue;

                // 取得した型のインスタンスを作成
                var obj = Activator.CreateInstance(type);

                //CommadList.Add(((sampleInterface)obj));
                
                // 処理を実行
                ((sampleInterface)obj).sample2();

                // アンロード実施
                alc.Unload();
                break;
            }
        }
    }

#結果
アンロードはできたが、CommadList処理をメソッド内に含めるアンロードが失敗する
実際の使用方法は、ロードしたオブジェクトを使いまわしたい為、外部で保持する必要があるのだが、保持してしまうとアンロードが出来なくなることが分かった。

また、CommadListにnullを入れてもダメ、CommadListをロード、アンロードする内部で記述するだけでもアンロードができなかった。

本当に閉じた状態でしか使用ができないようだ。

3
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2