2010-05-31 9 views
3

J'ai passé des heures à lire sur AppDomains, mais je ne suis pas sûr qu'ils fonctionnent comme j'espère.Est-ce que .NET AppDomains peut faire cela?

Si j'ai deux classes, Foo générique <T> à AppDomain # 1, Bar à AppDomain # 2:

App Domaine # 1 est l'application. App Domain # 2 est quelque chose comme un plugin, et peut être chargé et déchargé dynamiquement. AppDomain # 2 veut créer Foo <Barre> et l'utiliser. Foo <T> utilise beaucoup de classes dans AppDomain # 1 en interne.

Je ne veux pas AppDomain # 2 en utilisant objet foo avec réflexion, je veux qu'il utilise Foo <Bar> foo, avec tout le typage statique et la vitesse compilée qui va avec. Cela peut-il être fait en considérant que AppDomain # 1, contenant Foo <T>, n'est jamais déchargé?

Si tel est le cas, y a-t-il un accès distant lorsque vous utilisez Foo <Bar>?

Lorsque je décharge AppDomain # 2, le type Foo <Bar> est détruit?

éditer SO a dépouillé tous mes < >, les a rajoutés manuellement.

Répondre

6

Vous confondez types et les objets dans votre question qui le rend difficile à répondre. Le code dans un AD n'a aucun problème à utiliser des types qui sont également utilisés dans d'autres AD, il charge simplement l'assemblage. Mais un AD a son propre tas de garbage collecté, vous ne pouvez pas référencer directement les objets qui vivent dans une autre AD. Ils doivent être sérialisés sur la limite AD. Oui, Remoting à travers un IpcChannel le fera.

+0

IpcChannel n'est pas nécessaire. vous pouvez utiliser appdomain.CreateInstance pour faire cela pour vous. Tant que la classe en question est sérialisable ou marshalobjbyref, vous obtiendrez ce que vous voulez sans avoir à configurer de canaux d'accès distant. le .net runtime est assez intelligent pour savoir comment faire le remoting entre deux domaines d'applications avec une grande efficacité, car ils sont sur le même ordinateur. –

+0

Ok, donc si je vous comprends, je peux créer Foo ; instances dans AppDomain # 2 pas de problème et de les utiliser comme d'habitude - pas de communication à distance - il suffit de charger dans l'ensemble contenant Foo . J'ai vraiment besoin dans AppDomain # 1 est de séparer un ensemble contenant seulement les quelques singletons statiques à vie longue qui détiennent et gèrent mes ressources non gérées de sorte qu'il y ait seulement une copie de ceux-ci. Pas besoin d'avoir Foo ici. Lorsque Foo dans AppDomain # 2 utilise ces objets de AppDomain # 1, une sorte d'accès distant est nécessaire. Une façon de faire des appels de méthode statiques à travers AppDomains - quoi? – Eloff

+0

@Vagaus semble avoir la réponse, avoir les objets dans AppDomain # 1 sous-classe MarshalByRefObject et se retrouver avec des proxies aux singletons à long terme de AppDomain # 1, qui pourrait être le heureusement utilisé dans AppDomain # 2, sans doute marshalling arguments de méthode et les valeurs de retour à travers les limites AppDomain. – Eloff

1

Si vous souhaitez accéder à des objets traversent ces objets application Domaines doivent hériter de MarshalByRefObject; Dans un tel scénario, vous finirez avec un proxy à l'objet réel. De cette façon, il est possible de décharger le domaine d'application en toute sécurité (si vous essayez d'appeler le proxy, une exception sera levée).

Je suppose que ce que vous essayez d'accomplir est quelque chose comme:

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

Si vos types sont définis dans différents ensembles (ce qui est probable), vous définissez probablement une interface (dans un ensemble commun) et faire les types implémenter cette interface.

Espérons que cela aide.