在appdomains之间来回传递集合对象

时间:2012-10-27 13:46:34

标签: c# .net remoting appdomain

以下示例基于“Passing values back and forth appdomains”,其中Marc Gravell对appdomains之间的.Net远程处理问题提供了非常好的答案。我所做的是扩展它(非常天真?)期望它应该也适用于一个字符串数组。

问题是它只能以一种方式工作 - 创建的appdomain可以访问数组,但只能是readonly。我想要的是将更新的数组元素也恢复到原来的appdomain中。我甚至想用List<>这样做和词典<>对象。这可能吗?

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 个答案:

答案 0 :(得分: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!"!!!

<强>更新

我猜你必须clone实例并在从远程方法返回之前实例化new instance。简单workingstring的原因是 -

字符串为immutable,即每次使用不同的值对其进行初始化时,会在幕后创建一个new instance,就像new String()一样。因此,更新在其他appDomain中可见。

我用StringBuilder尝试了这个小事mutable,但是当你改变对象的内容时,没有为它们创建新的实例。

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"