/// <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中,以便我以后可以卸载它们。
我发布了第一个函数的评论,希望它能解释我正在尝试做什么。从子AppDomain调用第二个函数,希望程序集将被加载到那里。
这不起作用。
将CreateInstanceAndUnWrap的返回强制转换为Type I需要隐式意味着我需要将程序集加载到父域和子域中吗?如果是这样,我不会这样做。
我试图设置PrivateBinPath但是当我尝试沿着该路径加载程序集时,我怀疑它从未被探测过。我的基础是异常告诉我的。抛出异常表示无法找到程序集。异常中提到的路径始终是基目录,其中附加了程序集的名称。
我很乐意学习如何解决这个问题,以及我做错了什么。我恳求启蒙......认真......我跪在地上。
修改
我对异常消息不正确。它列出了程序集所在的路径。该路径在基本目录的子目录中解析。我最好的理论仍然是我没有正确设置基目录子目录的探测。
答案 0 :(得分:0)
尽管我付出了最大的努力,但我无法从基本目录以外的任何地方加载程序集。我将程序集复制到基目录,使用卷影副本将它们加载到缓存中,并立即从我的基目录中删除它们。这很麻烦,还有其他问题,但我觉得我现在可以管理的最好。