2009-12-06 25 views
1

Je m'excuse maintenant si ma prochaine explication n'a pas assez de sens; Je suis reconnu pour cela, bien que j'essaie de faire autrement. Je suis en train d'écrire un service qui utilise des plugins définis par l'utilisateur. Je suis en essayant de les isoler - en gardant leurs assemblys hors du domaine d'application du service - en utilisant des interfaces définies dans un assembly partagé.Résumé classes de base et appdomains

Ce qui me tue, c'est l'utilisation de classes de base abstraites. Il existe des fonctionnalités communes à toutes les implémentations de certaines des interfaces, donc les classes de base abstraites ont du sens. Si une base abstraite est dans l'assembly de service, alors tous les plugins qui la sous-classent obtiennent leurs assemblys glissés dans le domaine d'application du service. Cependant, il existe des membres internes dans la base abstraite (propriétés avec setters internes et getters publics) que le service utilise, il doit donc être dans le même assembly que le service pour que cela soit possible.

Il me semble que ce que je veux n'est pas possible, mais je crois aussi que c'est parce que je fais fausse route. J'essaie désespérément de faire un meilleur usage des bons modèles et pratiques dans cet exercice et d'apprendre en cours de route.

+0

Étant donné que les interfaces sont la clé, ce que j'ai fini par faire, c'est que la classe de base abstraite implémente une interface interne. Cette interface interne implémente une interface publique, de sorte que la classe de base implémente les membres publics et internes. Si un objet sous-classe la classe de base, alors je sais que j'ai accès à une propriété d'interface interne que je peux définir. Cela semble garder l'assemblage du plugin hors de l'appdomain principal! – redman

Répondre

0

Ce que vous voulez probablement, c'est une interface avec une classe de base abstraite qui implémente l'interface et dont les classes dérivées peuvent hériter. Dans ce cas, vous pouvez conserver votre séparation avec l'interface tout en fournissant la classe de base abstraite pour l'implémentation. Cela a également l'avantage que la classe de base abstraite est facultative.

0

Si le problème que vous tentez d'éviter est la fuite de l'assemblage de plug-in dans votre AppDomain de service, alors vous n'aurez pas ce problème si vous avez des membres internes ou non. Vous aurez simplement besoin que l'assembly de service soit disponible à l'intérieur du domaine plugin (et non l'inverse) et vous devrez probablement définir le type partagé dans l'assembly de service plutôt qu'un assembly séparé (si vous avez vraiment besoin de "internal" de l'autre assemblée). Imaginez que vous ayez la classe de base abstraite PluginBase définie dans ServiceLib.dll. Vous pouvez alors le code comme ceci dans votre principale AppDomain de service:

// Create a new AppDomain for the plugin 
AppDomain pluginDomain = AppDomain.CreateDomain("PluginDomain", null, new AppDomainSetup()); 

// Instantiate the plugin type (in the new AppDomain) 
// Note: assumes that PluginBase is MarshalByRefObject 
PluginBase plugin = (PluginBase)domain.CreateInstanceAndUnwrap("PluginLib", "PluginLib.PluginImp"); 

// Set any internal stuff now 
plugin.InternalDetails = "..."; 
+0

Et c'est en fait ce que je suis en train de faire. Cependant, lorsque je définis la propriété interne définie dans la classe de base, c'est à ce moment qu'elle amène l'assembly du plugin dans le domaine d'application du service. Je devine que c'est parce que c'est une base abstraite et que l'information de type est nécessaire de l'assemblée de module (et c'est vraiment un GUESS). – redman

+0

Hmm, j'ai juste essayé cela et il semble que je vois le même comportement que vous ... dès que vous chargez la classe dans l'autre AppDomain, il charge l'assembly de plug-in dans le principal AppDomain. Lorsque vous utilisez une interface, cela ne se produit pas, mais bien sûr cela ne vous aide pas à définir l'implémentation commune. Ce qui semble fonctionner est la définition d'une interface et d'une classe de base qui implémente l'interface; puis, lorsque vous chargez le type, vous ne lancez que vers l'interface et l'autre assemblage ne sera pas chargé. Cela peut ne pas faire tout à fait ce que vous voulez parce que les interfaces ne permettent pas la visibilité mixte. – bobbymcr

0

(Pour mon avenir et peut-être référence autres)

Il se trouve que ce fut un exercice un peu inutile. Une fois que le proxy de l'objet créé par le plugin était disponible dans d'autres domaines d'application, tout élément de cette classe de base définie par le service qui utilise le service de manière interne (comme une recherche sur une collection) l'objet de service dans l'appdomain du plugin, pas le singleton que j'essaye de fournir.

Je pense que je suis soit en train d'abandonner ma quête multidomaines, soit d'abandonner quoi que ce soit en interne. S'il n'y a pas d'opérations internes, la classe de base peut être séparée du service, mais elle doit interagir avec le service comme tout le reste. J'apprécie apprendre, mais je n'apprécie pas les bosses sur la tête le long du chemin.