【问题标题】:Passing collection objects back and forth between appdomains在 appdomains 之间来回传递集合对象
【发布时间】:2012-10-27 13:46:34
【问题描述】:

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

问题在于它只能以一种方式工作——创建的 appdomain 可以访问数组,但只能是只读的。我想要的是将更新后的数组元素也恢复到原始 appdomain 中。我什至想用 List 和 Dictionary 对象来做这件事。这可能吗?

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);
      }
   }
}

【问题讨论】:

    标签: c# .net remoting appdomain


    【解决方案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。简单的stringworking 的原因是-

    字符串是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"

    【讨论】:

    • 谢谢。这种技术似乎也适用于 List 和 Dictionary,并且可能适用于其他集合。所以我想我通常需要做的是,1)在我的远程代码开始时制作一个集合的克隆本地副本,2)通过修改本地副本对集合进行任何修改,以及 3)在返回之前从远程代码将集合对象的克隆本地副本分配给接口引用。但它确实看起来有点像kludge。您是否碰巧有任何信息链接来说明这是否是做这类事情的正确方法?
    • @RenniePet - 我已经用我的一些发现更新了答案,即为什么它适用于字符串而不适用于列表和字典。请检查更新的答案。
    • 谢谢。但你一定误读了我的评论。它确实适用于 List 和 Dictionary 使用你用新对象替换字段的技巧。我发现的另一件事是,对于远程方法来更新参数以便它反映在调用者的参数中,您必须在参数和参数上显式指定“ref”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    相关资源
    最近更新 更多