簡體   English   中英

C# 程序集 object 的壽命通過與 Activator.CreateInstance 的接口實例化

[英]Lifespan of C# Assembly object instantiated by interface with Activator.CreateInstance

我正在嘗試使用 C# 和 dotnet 的插件架構。 我發現以這種方式創建的任何實例在應用程序關閉之前都不會被收集。

我最初的想法是加載每個object並調用注冊方法,然后讓它死掉。 注冊方法將傳回需要知道它應該在未來何時加載的信息,並在那時創建一個新實例。 這將阻止我在不使用時保持 50 個左右的對象存活。

將一個簡單的 System.Diagnostics.Debug.Writeline 放入第一次循環通過的類的構造函數和終結器中不會破壞任何對象。 只有當我關閉應用程序時,才會發生任何終結器調用。 如果我做一個實驗,我有一個內部 IProduct 實例並加載幾個實例,我會得到 5 個構造函數調用,一旦我關閉 5 個終結器調用。

對於下面的內容,我創建了 2 個不同的 DLL,其中 1 個 class 每個都實現了接口。 所以我得到一個 Class1 構造函數調用和一個 Class2 構造函數調用。 但只有在關閉時才會調用析構函數。

我最初的期望是,一旦 IProduct myDLL 退出 scope(迭代/離開 for 循環)或者最壞的情況是 function 本身,就會調用終結器。 這被縮減為沒有數據從加載的 dll 傳遞到主程序,以確保我不會通過掛在參考上來保持任何活動,但我仍然看到相同的結果。

    void LoadProductPlugins()
    {
        string[] sFiles = Directory.GetFiles(Directory.GetCurrentDirectory() + "\\dll", "*.dll", SearchOption.TopDirectoryOnly);

        foreach (string strDll in sFiles)
        {
            Assembly assy = Assembly.LoadFile(strDll);

            Type[] types = (from t in assy.GetExportedTypes()
                                 where !t.IsInterface && !t.IsAbstract
                                 where typeof(IProduct).IsAssignableFrom(t)
                                 select t).ToArray();
            for (int i = 0; i < types.Length; i++)
            {
                IProduct myDLL = (IProduct) Activator.CreateInstance(types[i]);
            }
        }
    }

object 的生命周期管理沒有區別,無論是通過常規newCreateInstance還是任何其他可以想到的方法創建。 當需要 GC 並且特定的 object 不再可達時,將收集 object。

筆記:

  • 終結器僅作為完整 GC 通行證(第 2 代)的一部分被調用。 這會導致您在關閉時調用終結器時看到的行為,因為沒有足夠的 memory 使用量需要更早地進行 GC。
  • 在卸載 AppDomain 之前,程序集本身不會被卸載。 除非您為插件創建單獨的 AppDomain,否則將不會卸載程序集。 您可能想閱讀有關程序集加載/版本控制的內容 - 閱讀https://docs.microsoft.com/en-us/archive/blogs/suzcook/assembly-identity周圍的所有帖子將為您節省大量時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM