2017-10-08 101 views
1

我的目標是執行某些「一段代碼」,即用某些組件,比組件的多個版本。我這樣做的方式是通過執行在不同的AppDomain「一段代碼」,每一個程序集的版本。加載多個組件版本爲多個應用程序域

我能做到這一點,只有當「一段代碼」通過反射採用彙編,但我想是有「一段代碼」寫在強類型的方式。

換句話說,假設我有以下組件:

namespace ClassLibrary1 
{ 
    public class Class1 
    { 
     internal const string Version = "1.0.0.0"; 
     public string Method1() { return Version; } 
    } 
} 

此外,它擁有的AssemblyInfo.cs以下定義:

[assembly: AssemblyVersion(ClassLibrary1.Class1.Version)] 

現在讓我們假設我有一個「版本」文件夾中我有該組件的多個版本,例如:

/Versions/ 
├─ /1000/ 
│ └─ ClassLibrary1.dll 
├─ /1001/ 
│ └─ ClassLibrary1.dll 
└─ /1002/ 
    └─ ClassLibrary1.dll 

Now to執行「一段代碼」我使用下面的控制檯應用程序:

class Program 
{ 
    static void PieceOfCode(Assembly assembly) 
    { 
     Type class1Type = assembly.GetType("ClassLibrary1.Class1"); 
     dynamic class1 = Activator.CreateInstance(class1Type); 
     string vesion = class1.Method1(); 

     Console.WriteLine(vesion); 
    } 

    public sealed class SeparateDomainExecutor : MarshalByRefObject 
    { 
     public void Execute(Action<Assembly> action, string assemblyPath) 
     { 
      action(Assembly.LoadFrom(assemblyPath)); 
     } 
    } 

    static void Main(string[] args) 
    { 
     foreach (string file in Directory.EnumerateFiles(@"C:\Versions", "*.dll", SearchOption.AllDirectories)) 
     { 
      AppDomain domain = AppDomain.CreateDomain("ClassLibrary1 Domain"); 

      var type = typeof(SeparateDomainExecutor); 
      var runner = (SeparateDomainExecutor)domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName); 
      runner.Execute(PieceOfCode, file); 

      AppDomain.Unload(domain); 
     } 

     Console.Read(); 
    } 
} 

控制檯應用程序工作正常,但我想,以取代「PieceOfCode」這反映使用的東西,如下列:

static void PieceOfCode() 
{ 
    ClassLibrary1.Class1 class1 = new ClassLibrary1.Class1(); 
    Console.WriteLine(class1.Method1()); 
} 

這可能嗎?

我遇到的問題是PieceOfCode會使用某些特定版本的ClassLibrary1(可能是最新版本)編寫,我看不到我可以在單獨的AppDomain中「覆蓋」該版本。 我試過幾件事,但我總是FileLoadException結束。

+0

如果它是一個強大的命名程序集並且在加載應用程序之前知道該版本,則可以使用綁定重定向和更改app/web .config文件中的版本 –

+0

「強類型」是「多個版本」 。 .NET通過在類型標識中包含程序集的版本號來實現強類型檢查。一個強大的DLL地獄對抗措施,但顯然你想通過設計創造地獄。所以你根本不想這樣做。 –

+0

是的,確切地說。基本上,我想忽略那個強大的名字 - 地獄保護。 – bellpatricia

回答

1

不幸的是,當您在一個靜態類型的代碼片段中編寫ClassLibrary1.Class1時,您需要一個程序集引用,編譯器使用該引用來命名給定版本的類。雖然完全合格的名稱(typeof(Class1).AssemblyQualifiedName)不包含組件的路徑或文件名,只是程序集名稱和版本的類加載器有進一步的限制,您可能會注意到:

  • 它不能從不同的負載2班組件具有相同的名稱到同一個命名空間
  • 因爲路徑或文件名是不是程序集引用的一部分,你不能引用2個組件編譯時使用相同的強名稱

您使用Assembly.LoadFrom(...)和動態綁定的方式是我能想到的最好的。這就是通常從集成它們的應用程序處理不同版本的Office程序集的方式。

唯一可能的解決方案,我看到的是一段代碼分離成一個單獨的組件(比如說,MyStaticIntegration.dll)分別編譯它針對你的依賴(ClassLibrary1.dll)的每個版本,然後整合MyStaticIntegration的每個版本.dll到您的應用程序中的方式與之前使用ClassLibrary1.dll時的方式相同。

您的應用程序中仍會保留相同的動態牆,但您可以縮小動態使用的界面的範圍。

+0

謝謝你的回覆,不幸的是你證實了我的擔憂。儘管如此,感謝您提供的解決方案。 – bellpatricia

相關問題