2012-10-27 47 views
1

之間下面的示例是基於「Passing values back and forth appdomains」,其中馬克Gravell好心提供了一個非常好的回答有關應用程序域之間.Net遠程問題。我所做的是將它擴展爲一個(非常天真?)的期望,它也應該適用於一系列字符串。傳遞對象集合來回的AppDomain

的問題是,它只能一條路 - 創建的應用程序域可以訪問陣列,但是隻有隻讀。我想要的是將更新後的數組元素重新放回到原來的appdomain中。我甚至想用列表<>和字典<>對象來做到這一點。這可能嗎?

using System; 

namespace StackoverflowSample 
{ 
    class MyBoundaryObject : MarshalByRefObject 
    { 
     public void SomeMethod(AppDomainArgs ada) 
     { 
     Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + "; executing"); 
     ada.MyString = "working!"; 
     ada.MyStringArray[0] = "working!"; 
     string s = ada.MyStringArray[0]; // s is assigned value "a"!!! 
     } 
    } 


    public class AppDomainArgs : MarshalByRefObject 
    { 
     public string MyString { get; set; } 
     public string[] MyStringArray { get; set; } 
    } 


    static class Program 
    { 
     static void Main() 
     { 
     AppDomain domain = AppDomain.CreateDomain("Domain666"); 
     MyBoundaryObject boundary = (MyBoundaryObject) 
       domain.CreateInstanceAndUnwrap(
       typeof(MyBoundaryObject).Assembly.FullName, 
       typeof(MyBoundaryObject).FullName); 

     AppDomainArgs ada = new AppDomainArgs(); 
     ada.MyString = "abc"; 
     ada.MyStringArray = new string[] { "a", "b" }; 
     Console.WriteLine("Before: " + ada.MyString + " " + ada.MyStringArray[0]); 

     boundary.SomeMethod(ada); 

     Console.WriteLine("After: " + ada.MyString + " " + ada.MyStringArray[0]); 
     Console.ReadKey(); 
     AppDomain.Unload(domain); 
     } 
    } 
} 

回答

1

有時回來,我有這樣的要求也返回更新的列表回到主的AppDomain和我解決它使用創建new instance of a Listassign the desired values的解決方法。這應該爲你工作 -

ada.MyStringArray = new string[] { "working!", "b" }; 
string s = ada.MyStringArray[0]; // s will be assigned value "working!"!!! 

UPDATE

我想你必須clone的實例,並從遠程方法返回之前實例化一個new instance。對於其中的原因是working簡單string是 -

字符串是immutable即每次使用不同的值初始化它的時候,它會創建場景有點像new String()後面new instance。因此,更新在其他appDomain中可見。

我試過這個小東西,用StringBuildermutable,即當你改變對象的內容時,並沒有爲它們創建新的實例。

public class AppDomainArgs : MarshalByRefObject 
{ 
    public StringBuilder MyStringBuilder { get; set; } 
} 

public void SomeMethod(AppDomainArgs ada) 
{ 
    Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + "; executing"); 
    ada.MyString = "working!"; 
    ada.MyStringBuilder.Append(" working!"); 
} 

現在,看到輸出 -

Console.WriteLine("Before: " + ada.MyString + " " + ada.MyStringArray[0] + " " + 
         ada.MyStringBuilder);  
boundary.SomeMethod(ada);  
Console.WriteLine("After: " + ada.MyString + " " + ada.MyStringArray[0] + " " 
         ada.MyStringBuilder); 

你會看到StringBuilder對象是不變的。理想情況下,其價值應該是"a working!",但價值仍然是"a"

+0

謝謝。這種技術似乎也適用於List 和Dictionary ,並且可能用於其他集合。所以我想我通常需要做的是:1)在遠程代碼的開始創建一個克隆的集合本地副本,2)通過修改本地副本對集合進行任何修改,3)在返回之前從遠程代碼分配集合對象的克隆本地副本到接口引用。但它看起來有點像kludge一樣。你是否碰巧有任何信息鏈接,告訴你這是做這種事情的正確途徑? – RenniePet

+0

@RenniePet - 我用我的一些發現更新了答案,即爲什麼它適用於字符串,而不適用於列表和詞典。請檢查更新後的答案。 –

+1

謝謝。但是你必須誤解我的評論。它使用你的用新對象替換字段的技巧,對List <>和Dictionary <>起作用。我發現的另一件事是,對於遠程方法來更新參數,以便它反映回調用者的參數中,您必須在參數和參數中明確指定「ref」。 – RenniePet