2016-05-10 1 views
1

Actuellement, je compile et charge un assembly au moment de l'exécution. L'assembly contient toujours les mêmes espaces de noms et classes. Lorsque je fais cela plusieurs fois dans la même instance d'application, est-ce que l'assemblage le plus récent sera toujours utilisé, lors de la création de nouvelles instances des classes qui sont dans l'assembly? Ou n'est-ce pas garanti?Chargement avec la DLL compilée Roslyn à l'exécution plusieurs fois

Répondre

1

Vous créez exactement ce que vous essayez de créer. Cela peut être ou ne pas être ce que vous voulez créer, cependant. Très probablement, vos assemblys n'ont pas de nom spécifique, mais plutôt un nom unique randomisé - dans ce cas, les types sont entièrement différents et accidentellement similaires en ce qui concerne .NET. Les types de deux compilations différentes sont totalement indépendants et ne sont pas compatibles. Cela peut poser problème ou non lorsque vous y accédez via une interface définie en dehors de l'assemblage dynamique, en fonction de la manière dont vous utilisez les types.

Si vous ajoutez un nom d'assembly, la situation devient un peu plus compliquée. Vous ne pouvez pas charger le même assemblage deux fois (l'ancien n'est pas remplacé par le nouveau), vous devez donc changer la version. Cependant, deux versions d'un même assemblage ne peuvent pas être chargées dans le même domaine d'application (sauf si vous faites du "fun" avec AssemblyResolve etc. - mais c'est assez difficile à obtenir). Le second assemblage échouerait simplement à charger.

En fin de compte, la Type que vous essayez d'instancier est celui que vous ne instancier (sauf l'utilisation de redirections de liaison, qui sont amusants bonus: P). Si une partie de votre code reste sur une Type d'une compilation précédente, c'est ce qu'elle va créer.

+0

Merci pour votre réponse. Donc, je ne devrais pas avoir de problèmes, car dans ce cas précis, je ne tiens pas les instances de types qui sont définis dans un * ancien * assemblage. Merci beaucoup! Ouais, ils n'ont pas de nom, parce que j'ai déjà eu des problèmes en leur donnant des noms :) – BendEg

+1

@BendEg Yup, cela devrait fonctionner correctement.Notez que les anciens assemblys ne sont pas nettoyés, donc si vous faites la compilation souvent dans le même processus, vous pouvez les charger dans un AppDomain différent (vous pouvez décharger le domaine quand il n'est plus utile). – Luaan

1

Si votre question est si je charge un ensemble dans AppDomain

Assembly a1=Assembly.Load(Array of Assembly); 

Et puis changez le code avec Roslyn comme nom de classe et créer un nouveau montage de votre projet et le charger à nouveau

Assembly a2 =Assembly.Load(Array of Assembly); 

maintenant est-ce que a2 est chargé dans CurrentDomain? Ma réponse est non .a1 est maintenant dans CurrentDomain.

Vous pouvez le tester.

Donc, pour travailler avec un nouvel assemblage, vous devez utiliser la solution ci-dessous.

Vous devez charger cette assemblée dans un autre AppDomain et chaque fois que vous pouvez Décharger ce AppDomain et créer à nouveau et l'ensemble de la charge à nouveau

d'abord créer une classe qui currentDomain chargera exemple de ce à un autre AppDomain cet objet de La classe doit charger votre assembly et ses dépendances à la deuxième AppDomain.

// you can create this class in another project and 
// make assembly .because you need a copy of it in 
//folder that you set for ApplicationBase of second AppDomain 
public class AssemblyLoader : MarshallByRefObject 
{ 
    AssemblyLoader() 
    { 
     AppDomain.CurrentAppDomain.AssemblyResolve += LoaddependencyOfAssembly; 
    } 
public void LoaddependencyOfAssembly(object sender,) 
{ 
    //load depdency of your assembly here 
    // if you has replaced those dependencies to folder that you set for ApplicationBase of second AppDomain doesn't need do anything here 
} 
public Assembly asm {get;set;} 
public void LoadAssembly(MemoryStream ms) 
{ 
    asm= Assembly.Load(ms.ToArray()); 
} 
} 

dans lequel vous voulez charger l'assemblage

AppDomainSetup s=new AppDomainSetup(){ApplicationBase="anotherFolderFromYourAppBinFoldr}; 
AppDomain ad= AppDomain.CreateDomain("name",AppDomain.CurrentDomain.Evidence,s); 
Type t = typeof(AssemblyLoader); 
AssemblyLoader al = (AssemblyLoader) ad.CreateInstanceAndUnwrap(t.Assembly.FullName,t.FullName); 
// load assembly here by Stream or fileName 
al.LoadAssembly(ms); 
// now assembly loaded on ad 
// you can do your work with this assembly by al 
// for example create a method in AssemblyLoader to 
// get il of methods with name of them 
// Below IL is in CurrentDomain 
//when compiler goes to GetIlAsByteArray you are in second AppDomain 
byte[] IL = al.GetILAsByteArray("NameOfMethod"); 
//And unload second AppDomain 
AppDomain.Unload(ad); 
+0

Merci pour votre réponse. Je n'ai jamais travaillé avec différents AppDomains. Cela permet-il une communication facile entre le principal AppDomain et le nouveau créé? Merci – BendEg

+0

Je l'ai dit dans ma réponse.Vous pouvez par exemple obtenir il de méthodes dans l'assemblage et le retourner à AppDomain d'abord.Je vais modifier la réponse – mohsen

+0

Merci pour cette réponse détaillée et de travail. Je vais essayer cela et revenir à vous. +2 Si je pouvais ... – BendEg