2010-05-31 90 views
3

我花了幾個小時閱讀關於AppDomains的信息,但我不確定它們的工作方式與我所希望的完全相同。.NET AppDomains可以這樣做嗎?

如果我有兩個班,一般富<牛逼>中的AppDomain#1,酒吧中的AppDomain#2:

應用程序域#1是應用程序。 App Domain#2就像一個插件,可以動態加載和卸載。

AppDomain#2想創建Foo <Bar>並使用它。 Foo <T>在內部使用AppDomain#1中的大量類。

我不希望AppDomain#2使用反射對象foo,我希望它使用Foo <bar> foo,具有所有靜態類型和編譯速度。考慮到包含Foo <T>的AppDomain#1是否永遠不會被卸載?

如果是這樣,在使用Foo時是否發生任何遠程操作<Bar>?

當我卸載AppDomain#2時,類型Foo <Bar>被銷燬?

編輯 SO剝去了我所有的< >,手動添加它們。

回答

6

你正在混合你的問題中的類型和對象,這使得它很難回答。 AD中的代碼在使用其他AD中也使用的類型時沒有問題,它只是加載程序集。但是AD有自己的垃圾收集堆,你不能直接引用住在另一個AD中的對象。它們需要在AD邊界上進行序列化。是的,通過IpcChannel進行遠程訪問會這樣做。

+0

IpcChannel沒有必要。你可以使用appdomain.CreateInstance爲你做這個。只要有問題的類是可序列化的或者marshalobjbyref,你就可以得到你想要的,而不必配置任何遠程處理通道。 .net運行時足夠聰明,知道如何以高效率在兩個應用程序域之間進行遠程處理,因爲它們位於同一臺計算機上。 – 2010-05-31 17:28:55

+0

好吧,如果我瞭解你,我可以創建Foo ; AppDomain#2中的實例沒有問題,並且像正常一樣使用它們 - 沒有遠程處理 - 只需加載包含Foo 的程序集。 我真的需要在AppDomain#1中分離出一個只包含幾個靜態的長期單身人士的程序集,這些單身人員擁有和管理我的非託管資源,這樣只有一個這樣的副本。這裏不需要Foo 。 其中AppDomain#2中的Foo 使用來自AppDomain#1的這些對象,將需要某種遠程處理。通過AppDomain進行靜態方法調用的一些方式 - 什麼? – Eloff 2010-05-31 17:46:58

+0

@Vagaus似乎有答案,讓AppDomain#1的子類MarshalByRefObject中的對象,然後代理AppDomain#1中的長期單身人士,這可以在AppDomain#2中愉快地使用,毫無疑問,透明​​地編組方法參數和跨AppDomain邊界的返回值。 – Eloff 2010-05-31 17:57:34

1

如果您想跨對象域訪問對象,則這些對象需要從MarshalByRefObject繼承;在這種情況下,你最終會得到一個真實對象的代理。這樣,卸載應用程序域是安全的(如果您嘗試通過代理調用將拋出異常)。

我猜你正在試圖做到的是這樣的:如果你的類型在不同的組件(這是可能的),你可能會定義一個接口(在一個共同的組件)定義

using System; 
using System.Reflection; 

namespace TestAppDomain 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     AppDomain pluginsAppDomain = AppDomain.CreateDomain("Plugins"); 

     Foo foo = new Foo(); 
     pluginsAppDomain.SetData("Foo", foo); 

     Bar bar= (Bar) pluginsAppDomain.CreateInstanceAndUnwrap(Assembly.GetEntryAssembly().FullName, typeof (Bar).FullName); 
     bar.UseIt(); 

     AppDomain.Unload(pluginsAppDomain); 
     foo.SaySomething(); 
    } 
} 

class Bar : MarshalByRefObject 
{ 
    public void UseIt() 
    { 
     Console.WriteLine("Current AppDomain: {0}", AppDomain.CurrentDomain.FriendlyName); 
     Foo foo = (Foo) AppDomain.CurrentDomain.GetData("Foo"); 
     foo.SaySomething(); 
    } 
} 

class Foo : MarshalByRefObject 
{ 
    public void SaySomething() 
    { 
     Console.WriteLine("Something from AppDomain: {0}", AppDomain.CurrentDomain.FriendlyName); 
    } 
} 
} 

並使這些類型實現這個接口。

希望這會有所幫助。