2011-06-27 19 views
6

我創建了一個測試庫影子拷貝,以不鎖組件

public class Test 
{ 
    public int Add(int val1, int val2) 
    { 
     return val1 + val2; 
    } 
} 

一個項目來調用它:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 
using System.IO; 

namespace Loader 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      String path = @"...Lib.dll"; // path to lib 
      var name = Path.GetFileName(path); 

      AppDomainSetup setup = new AppDomainSetup 
      { 
       ApplicationBase = @"...", // directory where Lib.dll is 
       ShadowCopyFiles = "true", 
       ShadowCopyDirectories = @"..."// directory where Lib.dll is 
      }; 

      var appdomain = AppDomain.CreateDomain("Loader." + name, null, setup); 
      Assembly ass = Assembly.LoadFile(path); // <--- I think here is the problem, here where assembly is locked 
      Assembly assembly = appdomain.Load(ass.FullName); 

      dynamic a = assembly.CreateInstance("Lib.Test"); 

      Console.WriteLine(a.Add(1, 5)); 
     } 
    } 
} 

請幫忙找一下我做錯了?爲什麼我的程序集被鎖定?

編輯:用硬編碼集名稱:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 
using System.IO; 

namespace Loader 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AppDomainSetup ads = new AppDomainSetup(); 

      String fullPath = @"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Lib.dll"; 

      ads.ShadowCopyFiles = "true"; 
      ads.ApplicationName = "AppName"; 
      ads.ShadowCopyDirectories = Path.GetDirectoryName(fullPath); 
      //ads.ApplicationBase = Path.GetDirectoryName(fullPath); 
      //ads.PrivateBinPath = Path.GetDirectoryName(fullPath); 
      ads.CachePath = @"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Cache\"; 

      AppDomain ad = AppDomain.CreateDomain("myName" + ads.ApplicationName, null, ads); 

      ad.AssemblyResolve += new ResolveEventHandler(ad_AssemblyResolve); 

      Console.WriteLine(ad.ShadowCopyFiles); 
      Console.WriteLine(ad.SetupInformation.ShadowCopyDirectories); 

      try 
      { 
       //Assembly assembly = ad.Load(AssemblyName.GetAssemblyName(fullPath)); 
       //dynamic obj = ad.CreateInstanceAndUnwrap(assembly.GetName().Name, "Lib.Test"); 

       dynamic obj = ad.CreateInstanceAndUnwrap("Lib", "Lib.Test"); 

       Console.WriteLine(obj.Add(1, 7)); 

       Console.ReadKey(); 

       Console.WriteLine(obj.Add(1, 90)); 
      } 
      catch(Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
     } 

     static Assembly ad_AssemblyResolve(object sender, ResolveEventArgs args) 
     { 
      return Assembly.LoadFile(@"c:\users\myuser\documents\visual studio 2010\Projects\ShadowCopy\Loader\bin\Debug\Lib.dll"); 
     } 
    } 
} 

有趣的是,緩存assebly也被鎖定。

編輯2:

這裏是代碼行阻擋組件

Console.WriteLine(obj.Add(1, 7)); 

因此,一旦在Lib.Test的方法訪問的assenbly被阻止。

什麼是解決方案?

+0

請發佈您正在獲取的確切錯誤。 –

+0

我說過的確切問題是Lib。dll程序集被鎖定。 例如,一旦應用程序正在運行,我無法回報它。 – NDeveloper

+0

您需要在第三個程序集中使用接口,以防止代碼將構造類型加載到主AppDomain中。不要使用LoadFile。 –

回答

0

你有兩種選擇,你需要在運行時間之前查找程序集名稱,並對其進行硬編碼,或者如果你不知道以前的運行時間,則需要編寫第二個庫,但您知道FullName並加載到AppDomain中。第二個庫將是有一個函數

public Assembly GetAssemblyForOtherAppDomain(string path) 
{ 
    return Assembly.LoadFile(path) 
} 

這應該在新的AppDomain加載你的目標沒有鎖定它應該有一個卷影副本打開一個類。

編輯:爲何你的方法不奏效,你在哪裏說得對,在負載鎖定它,once a assembly is loaded in to a AppDomain it can not be unloaded.

+0

當然,我知道程序集名稱......但它不會幫幫我。我試過......同樣的問題。 – NDeveloper

+0

請檢查使用新代碼更新的問題。 – NDeveloper

1

你加載程序集到主AppDomain中,當您運行Assembly.LoadFile(),其鎖定該文件。如果你想直接將它加載到你的AppDomain中,你需要直接使用AppDomain.Load(),允許AppDomain根據你指定的參數來解析它。請注意,由於程序集未加載到主AppDomain中,因此您的Main方法無法訪問該類型。你Lib.Test需要從MarshalByRefObject導出,以便編組系統可以創建一個代理(這進一步被包裹成一個動態代理,當你把它分配給動態。)


編輯:

在進一步思考,我懷疑這裏的問題是,爲了調用動態代理上的方法,它必須反映在對象上(它本身就是您的其他AppDomain中的實例的透明代理)。如果它最終反映(而不是'hidden'透明代理類型),這會導致它在本地AppDomain中加載程序集的副本(從而鎖定它)。這就是爲什麼當使用AppDomain隔離時您通常會將該對象投射到在「主」應用程序和託管的AppDomain都可以引用的單獨程序集中定義的接口。他們每個都會加載他們自己的接口程序集副本,但是現在'實現'程序集是孤立的。

+0

請參閱編輯的代碼...沒有Assembly.LoadFile。 另外我從MarshalByRefObject派生了Lib.Test,並設置了[Serializable],但仍然一樣....我無法想象我需要做什麼。 – NDeveloper

+0

@NDeveloper,在這種新的情況下,你迫使AppDomain通過調用LoadFile來解析程序集,LoadFile繞過陰影複製並直接加載文件。如果您希望它使用影子複製機制加載文件,則需要將程序集的FullName傳遞給CreateInstanceAndUnwrap,並允許AppDomain執行自己的文件解析。 –

+0

但ad_AssemblyResolve從未調用過,因此您所描述的所有內容都是如此。 – NDeveloper