c#将程序集加载到子域

时间:2014-03-06 15:22:46

标签: c# .net-3.5 load .net-assembly appdomain

    /// <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但是当我尝试沿着该路径加载程序集时,我怀疑它从未被探测过。我的基础是异常告诉我的。抛出异常表示无法找到程序集。异常中提到的路径始终是基目录,其中附加了程序集的名称。

我很乐意学习如何解决这个问题,以及我做错了什么。我恳求启蒙......认真......我跪在地上。

修改

我对异常消息不正确。它列出了程序集所在的路径。该路径在基本目录的子目录中解析。我最好的理论仍然是我没有正确设置基目录子目录的探测。

1 个答案:

答案 0 :(得分:0)

尽管我付出了最大的努力,但我无法从基本目录以外的任何地方加载程序集。我将程序集复制到基目录,使用卷影副本将它们加载到缓存中,并立即从我的基目录中删除它们。这很麻烦,还有其他问题,但我觉得我现在可以管理的最好。