我正在開發一個解決方案,其中服務在後臺連續運行,並且可以在運行時添加/刪除插件DLL。該服務將在需要時加載必要的插件,運行並卸載它們。這是卸載部分是目前給我帶來的麻煩:一旦某個類第一次成功加載(變量tc),即使更新了DLL文件,它也不會重新加載。我想我不會正確地卸載班級/程序集/ appdomain,所以我希望得到一些關於走這最後一英里的建議。C#如何正確地從內存中卸載該類?
編輯:我更新了這篇文章,以反映代碼中的最新變化,並解釋卸載的確切時間沒有影響:Linux Ubuntu(通過Mono)沒有出現問題,但它存在於Windows 2008 Server上,我試圖用一個更新的文件版本替換某個插件DLL。看起來,.NET框架已經緩存在程序集的某個地方,並且很快樂,不用重新加載它。 DLL文件名不會改變,但File Version屬性不同,所以我期望運行時將以前加載的DLL版本與加載的版本進行比較,如果版本號不同,則使用新版本。如果我稍微更改代碼以從具有不同名稱的DLL文件加載程序集,則重新加載按預期發生。
using System;
using System.Reflection;
namespace TestMonoConsole
{
public interface ITestClass
{
void Talk();
}
class MainClass
{
public static void Main (string[] args)
{
string pluginPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string classAssembly = "TestClass";
string className = "TestMonoConsole.TestClass";
string command = "";
do
{
try
{
System.AppDomain domain = System.AppDomain.CreateDomain(classAssembly);
string pluginAssemblyFile = pluginPath + "/" + classAssembly + ".dll";
System.IO.StreamReader reader = new System.IO.StreamReader(pluginAssemblyFile, System.Text.Encoding.GetEncoding(1252), false);
byte[] b = new byte[reader.BaseStream.Length];
reader.BaseStream.Read(b, 0, System.Convert.ToInt32(reader.BaseStream.Length));
domain.Load(b);
reader.Close();
ITestClass tc = (ITestClass) Activator.CreateInstance(domain, classAssembly, className).Unwrap();
tc.Talk();
System.AppDomain.Unload(domain);
}
catch (System.IO.FileNotFoundException e)
{
Console.WriteLine (String.Format("Error loading plugin: assembly {0} not found", classAssembly));
}
command = Console.ReadLine();
} while (command == "");
}
}
}
任何異常都會被捕獲或登錄到事件查看器中。如果是,那麼請在這裏發佈例外 – HatSoft 2012-07-05 19:18:27
我在某處讀到一個常見的技巧是生成一個新的應用程序域,並在不再需要它時終止它 – rekire 2012-07-05 19:20:52
在事件查看器中沒有捕獲任何異常,也沒有任何事件發生。 – Passiday 2012-07-05 22:00:50