/// <summary>
/// This function loads a list of assemblies based on their file paths.
/// This function is intended to load the assemblies into another application domain than the main
/// one so that the assemblies can be unloaded when the application domain is unloaded.
///
/// See below to understand how this function achieves loading assemblies into a domain other than
/// the current one.
///
/// FIRST a new domain is created ---
/// - load the assembly into a child domain of the domain which will execute any code from a plugin.
/// NEXT the current assembly is loaded into the child domain ---
/// - this is MUCH easier than dealing another assembly into a child domain
/// - this assembly owns the definition of this PluginLoader class which will take full advantage of
/// NEXT get a PluginLoader instance from the child domain you just created ---
/// - since this instance is from the child domain anything you do with it will affect the child
/// domain and not the current one
/// - we want to load assemblies into the child domain so this is exactly what we want.
/// NEXT load the plugin assemblies into the child domain
/// - we leverage Assembly.LoadFrom which is MUCH easier to make use of than AppDomain.Load
/// - Assembly.Load* is the preferred method of loading assemblies and this is made abundantly
/// clear in any attempt to use AppDomain.Load in a generic fashion.
///
/// CRITICAL KNOWLEDGE
/// - PluginLoader MUST derive from MarshalByRefObject or this will WILL NOT WORK.
/// </summary>
/// <param name="pathsToAssemblies"></param>
/// <param name="plugInfo"></param>
/// <returns></returns>
static public bool LoadPluginAssemblies(string pluginName, List<string> pathsToAssemblies, out PluginInformation plugInfo)
{
try
{
string parentAssemblyName = Assembly.GetExecutingAssembly().FullName;
#region Create child domain and setup tracking for it
AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
ads.PrivateBinPath = "Assemblies";
//ads.PrivateBinPathProbe = "pluto_is_not_a_planet";
plugInfo = new PluginInformation(pluginName, AppDomain.CreateDomain(pluginName,null,ads));
#endregion //Create child domain and setup tracking for it
#region Load executing assembly into child domain
plugInfo.ChildDomain.Load(parentAssemblyName);
#endregion //Load executing assembly into child domain
#region Get PluginLoader from child domain
PluginLoader plugLoader =
(PluginLoader)plugInfo.ChildDomain.CreateInstanceAndUnwrap(parentAssemblyName, "DynamicAssemblyLoadTester.PluginLoader");
#endregion //Get PluginLoader from child domain
#region Load assemblies into child domain
foreach (string assemblyPath in pathsToAssemblies)
{ plugInfo.m_assembliesInDomain.Add(plugLoader._loadAssemblyIntoChildDomain(assemblyPath)); }//end for
#endregion //Load assemblies into child domain
}
catch (System.Exception ex)
{
Console.WriteLine("Plugin Load Failure: " + ex.Message);
plugInfo = null;
return false;
}//end try-catch
return true;
}//end function
private Assembly _loadAssemblyIntoChildDomain(string assemblyPath)
{
try
{
return Assembly.LoadFrom(assemblyPath);
}
catch (System.Exception ex)
{
Console.WriteLine("Failed to load assembly into child domain: " + ex.Message);
return null;
}//end try-catch
}//end function
我試圖將一些程序集加載到單獨的AppDomain中,以便稍後能夠卸載它們。c#將子程序集加載到子域
我發佈了第一個函數的註釋,希望它能解釋我正在嘗試做什麼。第二個函數是從子AppDomain調用的,希望程序集將在那裏加載。
這不起作用。
是否將CreateInstanceAndUnWrap的返回值轉換爲類型I需要隱含地表示我需要將程序集加載到父域和子域中?如果是這樣,我不會那樣做。
我試圖設置PrivateBinPath,但是當我嘗試加載沿着該路徑的程序集時,我懷疑它從未被探測過。我根據例外情況告訴我的。拋出異常,表示無法找到程序集。異常中提到的路徑始終是我的程序集名稱追加到它的基本目錄。
我很喜歡學習如何解決這個問題,以及我所做的是錯誤的。我懇求啓蒙......認真......我跪在地上。
編輯
我是不正確有關異常的消息。它列出了程序集所在的路徑。該路徑在基本目錄的子目錄中解析。我最好的理論仍然是,我沒有正確地設置基礎目錄的子目錄的探測。
你是什麼意思*這不起作用*。你會得到錯誤,異常或程序集是不是加載到你的新域?您可以嘗試設置一個代理對象 - 本身 - 除了在對象上下文中加載程序集外別無其他。請注意,跨越AppDomain邊界的對象(由CreateInstanceAndUnWrap創建的對象)需要從MarshalByRefObject派生。 – ElGauchooo
PluginLoader從MarshalByRefObject派生。這是我看到的錯誤。 ...無法加載文件或程序集'file:/// O:\ HP_WORK2 \ I ... \ Assemblies \ MyAssembly.dll'或其某個依賴項。該系統找不到指定的文件。 –
程序集MyAssembly不會加載到子域中。第二個函數拋出異常。這是當我嘗試通過穿過AppDomain邊界的對象將程序集加載到子域中時。所有的代碼都屬於PluginLoader。 TPluginLoader是對子域內對象的引用。我不能像我所希望的那樣使用PluginLoader將程序集加載到子域中。 –