tags:

views:

104

answers:

2

I've spent hours reading up about AppDomains, but I'm not sure they work quite like I'm hoping.

If I have two classes, generic Foo<T> in AppDomain #1, Bar in AppDomain #2:

App Domain #1 is the application. App Domain #2 is something like a plugin, and can be loaded and unloaded dynamically.

AppDomain #2 wants to create Foo<Bar> and use it. Foo<T> uses lots of classes in AppDomain #1 internally.

I don't want AppDomain #2 using object foo with reflection, I want it to use Foo<Bar> foo, with all the static typing and compiled speed that goes with it. Can this be done considering that AppDomain #1, containing Foo<T>, is never unloaded?

If so, does any remoting take place here when using Foo<Bar>?

When I unload AppDomain #2, the type Foo<Bar> is destroyed?

edit SO stripped all my <>, added them back manually.

+6  A: 

You are mixing types and objects in your question which makes it hard to answer. Code in an AD has no trouble using types that are also used in other ADs, it simply loads the assembly. But an AD has its own garbage collected heap, you cannot directly reference objects that live in another AD. They need to be serialized across the AD boundary. Yes, Remoting across an IpcChannel will do so.

Hans Passant
IpcChannel is not necessary. you can use appdomain.CreateInstance to do this for you. as long as the class in question is either serializable or marshalobjbyref, you'll get what you want without having to configure any remoting channels. the .net runtime is smart enough to know how to do the remoting between two app domains with high efficiency because they are on the same computer.
Derick Bailey
Ok, so if I understand you, I can create Foo<Bar>; instances in AppDomain #2 no problem and use them as normal - no remoting - just load in the assembly containing Foo<T>.I really need in AppDomain #1 is to separate out an assembly containing just the few static long-lived singletons that hold and manage my unmanaged resources so that there is only one copy of these. No need to have Foo<T> here.Where Foo<Bar> in AppDomain #2 uses these objects from AppDomain #1 some sort of remoting would be needed. Some way of doing static method calls across AppDomains - what?
Eloff
@Vagaus seems to have the answer, have the objects in AppDomain #1 subclass MarshalByRefObject and then end up with proxies to the long-lived singletons from AppDomain #1, which could the be happily used in AppDomain #2, no doubt transparently marshalling method arguments and return values across the AppDomain boundaries.
Eloff
+1  A: 

If you want to access objects cross app domains these objects need to inherit from MarshalByRefObject; in such scenario you'll end up with a proxy to the real object. This way it's safe to unload the application domain (if you try to call through the proxy an exception will be thrown).

I guess that what you are trying to accomplish is something like:

using System;
using System.Reflection;

namespace TestAppDomain
{
class Program
{
    static void Main(string[] args)
    {
        AppDomain pluginsAppDomain = AppDomain.CreateDomain("Plugins");

        Foo foo = new Foo();
        pluginsAppDomain.SetData("Foo", foo);

        Bar bar= (Bar) pluginsAppDomain.CreateInstanceAndUnwrap(Assembly.GetEntryAssembly().FullName, typeof (Bar).FullName);
        bar.UseIt();

        AppDomain.Unload(pluginsAppDomain);
        foo.SaySomething();
    }
}

class Bar : MarshalByRefObject
{
    public void UseIt()
    {
        Console.WriteLine("Current AppDomain: {0}", AppDomain.CurrentDomain.FriendlyName);
        Foo foo = (Foo) AppDomain.CurrentDomain.GetData("Foo");
        foo.SaySomething();
    }
}

class Foo : MarshalByRefObject
{
    public void SaySomething()
    {
        Console.WriteLine("Something from AppDomain: {0}", AppDomain.CurrentDomain.FriendlyName);
    }
}
}

If your types are defined in different assemblies (which is likely) you'll probably define an interface (in a common assembly) and make the types implement this interface.

Hope this helps.

Vagaus