web-dev-qa-db-fra.com

Comment décharger un assemblage de l'appdomain principal?

J'aimerais savoir comment décharger un assemblage chargé dans l'appdomain principal.

J'ai le code suivant:

var Assembly = Assembly.LoadFrom( FilePathHere );

J'ai besoin/veulent pouvoir décharger cet assembly lorsque je suis terminé.

Merci de votre aide.

42
Derik Whittaker

pour les versions .NET CORE 3.0 et version ultérieure:

Vous pouvez maintenant décharger des assemblages. Notez que AppDomains ne sont plus disponibles dans .NET CORE. Au lieu de cela, vous pouvez créer un ou plusieurs assemblages, chargez vos assemblages via ce contexte, puis déchargez ce contexte. Voir assemblageyloadcontext ou ce tutoriel qui simule le chargement d'un plugin puis le décharge .

pour les versions .NET avant .NET Noyau 3, y compris NetFramework 4 et Basse

Vous ne pouvez pas décharger un assemblage d'une appdomaine. Vous pouvez détruire des AppDomains, mais une fois qu'un assemblage est chargé dans une appdomaine, il est là pour la vie de l'AppDomain.

Voir l'explication de Jason Zander de pourquoi n'y a-t-il pas une méthode assemblée.unload?

Si vous utilisez 3.5, vous pouvez utiliser le cadre AdidIn pour faciliter la gestion/l'appel dans différentes AppDomains (que vous peut Déchargement, déchargement de tous les assemblages). Si vous utilisez des versions avant cela, vous devez créer une nouvelle Appdomain vous-même pour le décharger.

35
Philip Rieck

Je sais aussi que c'est très vieux, mais peut aider quelqu'un qui a cette question! Voici une façon dont j'ai trouvé le faire! à la place d'utiliser:

var Assembly = Assembly.LoadFrom( FilePathHere );

utilisez ceci:

var Assembly = Assembly.Load( File.ReadAllBytes(FilePathHere));

Cela charge réellement le "contenu" du fichier d'assemblage, au lieu du fichier lui-même. Ce qui signifie qu'il n'y a pas de verrouillage de fichier placé sur le fichier d'assemblage! Donc, maintenant, il peut être copié, supprimé ou mis à niveau sans fermer votre application ni essayer d'utiliser une appdomaine distincte ou un maréchalage!

Avantages : très simple à corriger avec un 1 paquebot de code! Inconvénients : Impossible d'utiliser AppDomain, Assembly.Location ou Assembly.CodeBase.

Maintenant, il vous suffit de détruire tout instances créé sur l'assembly. Par exemple:

Assembly = null;
23
Kirk Herron

Vous ne pouvez pas décharger un assemblage sans décharger l'appdomaine entière. Voici pourquoi :

  1. Vous exécutez ce code dans le domaine de l'application. Cela signifie qu'il existe potentiellement des sites d'appel et des piles d'appel avec des adresses qui s'attendent à continuer à travailler.

  2. Dites que vous avez réussi à suivre toutes les poignées et références à l'exécution déjà d'un code par un assemblage. En supposant que vous n'ayez pas NGen le code, une fois que vous avez libéré l'Assemblée, vous n'avez que libéré les métadonnées et IL. Le code JIT'D est toujours attribué dans le tas de chargeur de domaine d'applications (les méthodes JIT'D sont allouées séquentiellement dans un tampon dans l'ordre dans lequel ils sont appelés).

  3. Le numéro final concerne le code chargé partagé, autrement plus formellement le savoir sous le nom de "Neutre de domaine" (départ/partagé sur l'outil Ngénique). Dans ce mode, le code d'un assemblage est généré pour être exécuté à partir de n'importe quel domaine d'application (rien de câblé dur).

Il est recommandé de concevoir votre application autour de la limite de domaine d'application naturellement, où le déchargement est entièrement pris en charge.

15
Mark Cidade

Vous devez charger vos assemblages temporaires dans un autre AppDomain et lorsque vous n'êtes pas utilisé, vous pouvez décharger ce AppDomain. C'est sûr et rapide.

10
Nipun

Si vous souhaitez avoir un code temporaire qui peut être déchargé par la suite, en fonction de vos besoins, la classe DynamicMethod peut faire ce que vous voulez. Cela ne vous donne pas de cours, cependant.

4
Khoth

Je connais son vieux mais pourrait aider quelqu'un. Vous pouvez charger le fichier à partir du flux et le relâcher. Cela a fonctionné pour moi. J'ai trouvé la solution [~ # ~] ici [~ # ~ ~] .

J'espère que ça aide.

Voici un bon exemple de compilation et d'exécution de la DLL pendant le temps d'exécution, puis de décharger toutes les ressources: http://www.west-wind.com/presentions/dynamiccode/dynamiccode.htm

1
GenZiy

Comme alternative, si l'assemblage était juste chargé en premier lieu, pour vérifier les informations de l'assemblage comme le public de l'ordre public, la meilleure façon de ne pas le charger, et plutôt de vérifier les informations en chargement de l'annonce de l'Assemblée au début:

AssemblyName an = AssemblyName.GetAssemblyName ("myfile.exe");
byte[] publicKey = an.GetPublicKey();
CultureInfo culture = an.CultureInfo;
Version version = an.Version;

ÉDITER

Si vous devez refléter les types d'assemblage sans obtenir l'assemblage dans votre domaine d'application, vous pouvez utiliser le Assembly.ReflectionOnlyLoadFrom méthode. Cela vous permettra de regarder les types de types dans l'Assemblée mais ne vous permettra pas de les instantiez et ne chargera pas non plus l'assemblage dans l'appdomain.

Regardez cet exemple comme exlanation

public void AssemblyLoadTest(string assemblyToLoad)
{
    var initialAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //4

    Assembly.ReflectionOnlyLoad(assemblyToLoad);
    var reflectionOnlyAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //4

    //Shows that Assembly is NOT loaded in to AppDomain with Assembly.ReflectionOnlyLoad
    Assert.AreEqual(initialAppDomainAssemblyCount, reflectionOnlyAppDomainAssemblyCount); // 4 == 4

    Assembly.Load(assemblyToLoad);
    var loadAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //5

    //Shows that Assembly is loaded in to AppDomain with Assembly.Load
    Assert.AreNotEqual(initialAppDomainAssemblyCount, loadAppDomainAssemblyCount); // 4 != 5
}
0
Gerrie Pretorius