3

次のサンプルは、「appdomain 間で値をやり取りする」に基づいています。ここで、Marc Gravell は、appdomain 間の .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);
      }
   }
}
4

1 に答える 1

1

しばらく前に、更新されたリストを Main AppDomain に戻すというこの要件もあり、 anew instance of a Listとを作成する回避策を使用して解決しましたassign 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"です。

于 2012-10-27T14:24:56.447 に答える