11

I have the following code:

    public class AppDomainArgs : MarshalByRefObject {
        public string myString;
    }

    static AppDomainArgs ada = new AppDomainArgs() { myString = "abc" };

    static void Main(string[] args) {
        AppDomain domain = AppDomain.CreateDomain("Domain666");
        domain.DoCallBack(MyNewAppDomainMethod);
        Console.WriteLine(ada.myString);
        Console.ReadKey();
        AppDomain.Unload(domain);
    }

    static void MyNewAppDomainMethod() {
        ada.myString = "working!";
    }

I thought make this would make my ada.myString have "working!" on the main appdomain, but it doesn't. I thought that by inhering from MarshalByRefObject any changes made on the 2nd appdomain would reflect also in the original one(I thought this would be just a proxy to the real object on the main appdomain!)?

Thanks

devoured elysium
  • 101,373
  • 131
  • 340
  • 557

1 Answers1

21

The problem in your code is that you never actually pass the object over the boundary; thus you have two ada instances, one in each app-domain (the static field initializer runs on both app-domains). You will need to pass the instance over the boundary for the MarshalByRefObject magic to kick in.

For example:

using System;
class MyBoundaryObject : MarshalByRefObject {
    public void SomeMethod(AppDomainArgs ada) {
        Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + "; executing");
        ada.myString = "working!";
    }
}
public class AppDomainArgs : MarshalByRefObject {
    public string myString { 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";
         Console.WriteLine("Before: " + ada.myString);
         boundary.SomeMethod(ada);
         Console.WriteLine("After: " + ada.myString);         
         Console.ReadKey();
         AppDomain.Unload(domain);
     }
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 2
    I don't understand "How would be that?", but if you want an example; added. – Marc Gravell Aug 09 '09 at 07:06
  • I just run your code and it does what i am looking for! Thanks! Now I'll look at it carefully to understand what's happing in there. – devoured elysium Aug 09 '09 at 07:17
  • 2
    The important points; I need a method (`SomeMethod`) that passes an instance of `AppDomainArgs` over the boundary; this method must *itself* be on a `MarshalByRefObject`, and we want the `MyBoundaryObject` object to be in the other app-domain (`CreateInstanceAndUnwrap`). – Marc Gravell Aug 09 '09 at 07:22
  • But what is the reason that my code, having both Main() and MyNewAppDomainMethod() refering to a global variable, don't actually refer to the same variable? Shouldn't it be the same than declaring the variable and passing it into the method, like you do in your MyBoudaryObject.SomeMethod()? – devoured elysium Aug 09 '09 at 07:28
  • Better yet, is there any book where they explain well this boundary things, so I can understand the basis of this? – devoured elysium Aug 09 '09 at 07:33
  • 2
    Simply; instance fields are scoped by the instance; static fields are scoped by the `AppDomain`. Your references to `ada` are actually "`ada` in the current app-domain" - which is different for the code in `Main` (executing on the primary app-domain) and `MyNewAppDomainMethod` (executing in `"Domain666"`). Re books - I don't know, sorry. – Marc Gravell Aug 09 '09 at 07:38
  • So having my myString property static won't help in anything, as MarshalByRefObject only applies to instance fields, right? – devoured elysium Aug 09 '09 at 07:41
  • @Marc, or anyone else knowledgeable, would you mind taking a look at this http://stackoverflow.com/questions/13100718/passing-collection-objects-back-and-forth-between-appdomains , and perhaps commenting on the situation. – RenniePet Oct 27 '12 at 20:54
  • @RenniePet does "don't expect arrays to keep in sync between app-domains" count as an answer? – Marc Gravell Oct 27 '12 at 21:36
  • @Marc, thanks, an answer, even a disclaimer, is always a bit more knowledge, and that's good. But do you have any suggestions for possible other (better?) workarounds than the answer on that thread? If not, thanks again. – RenniePet Oct 27 '12 at 21:48
  • @RenniePet not really, no. IMO, when working with app-domains, the easiest-to-keep-sane approach is to treat it as message passing - so the only bridges are discreet "this sent me a message, which I can process". In most of my implementations, I try to keep it so that the **only** code that even knows there are two domains is a simple message send/receive handler. Beyond that: I treat them as if they were entirely separate. Most of the headaches go away if you keep it really really simple. – Marc Gravell Oct 27 '12 at 22:40