2014-03-06 62 views
0
/// <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,但是當我嘗試加載沿着該路徑的程序集時,我懷疑它從未被探測過。我根據例外情況告訴我的。拋出異常,表示無法找到程序集。異常中提到的路徑始終是我的程序集名稱追加到它的基本目錄。

我很喜歡學習如何解決這個問題,以及我所做的是錯誤的。我懇求啓蒙......認真......我跪在地上。

編輯

我是不正確有關異常的消息。它列出了程序集所在的路徑。該路徑在基本目錄的子目錄中解析。我最好的理論仍然是,我沒有正確地設置基礎目錄的子目錄的探測。

+1

你是什麼意思*這不起作用*。你會得到錯誤,異常或程序集是不是加載到你的新域?您可以嘗試設置一個代理對象 - 本身 - 除了在對象上下文中加載程序集外別無其他。請注意,跨越AppDomain邊界的對象(由CreateInstanceAndUnWrap創建的對象)需要從MarshalByRefObject派生。 – ElGauchooo

+0

PluginLoader從MarshalByRefObject派生。這是我看到的錯誤。 ...無法加載文件或程序集'file:/// O:\ HP_WORK2 \ I ... \ Assemblies \ MyAssembly.dll'或其某個依賴項。該系統找不到指定的文件。 –

+0

程序集MyAssembly不會加載到子域中。第二個函數拋出異常。這是當我嘗試通過穿過AppDomain邊界的對象將程序集加載到子域中時。所有的代碼都屬於PluginLoader。 TPluginLoader是對子域內對象的引用。我不能像我所希望的那樣使用PluginLoader將程序集加載到子域中。 –

回答

0

儘管我盡了最大努力,但無法從基本目錄中的任何位置加載程序集。我會將程序集複製到基本目錄,使用卷影副本將它們加載到緩存中,並立即從基本目錄中刪除它們。這是混亂的,還有其他問題,但這是我認爲我現在可以管理的最好的。

相關問題