2016-03-12 1 views
0

Je veux faire une fonction d'assemblage pour les scripts reloadable. (Donc, je peux déboguer des scripts plus rapide)C Temp # Décharger appdomain alors que principale appdomain utilise MethodInfo de température

Les travaux de génération dll et le chargement aussi. Le problème principal est que j'utilise les fonctions de mon AppDomain temporaire dans mon AppDomain principal. La DLL semble être liée à mon AppDomain principal aussi, parce que je ne peux pas le supprimer pendant que le programme est en cours d'exécution. Si je supprime toutes les références MethodInfo de mon contexte principal AppDomain, je n'ai aucun problème à le supprimer.

Ici vous pouvez voir comment le programme fonctionne:

  • Generate DLL de processus externe
  • charge DLL par (temp AppDomain) .DoCallBack (...)
  • type Get & MethodInfo et appel il.
  • AppDomain.Unload (température AppDomain)

Donc, si je saute l'étape 3, je n'ai pas de problèmes deleten la dll. Mais je ne peux pas vérifier si le retour de la fonction montre vraiment la valeur mise à jour (que je modifie dans le script).

J'ai posté le code source pour chaque étape ici: 1.

//This actually isn`t as important for you  
Process assemblyGeneration = new Process(); 
    assemblyGeneration.StartInfo.FileName = AppDomain.CurrentDomain.BaseDirectory + @"lib\AssemblyCompiler.exe"; 
    assemblyGeneration.StartInfo.Arguments = "\"" + AppDomain.CurrentDomain.BaseDirectory + "script.dll\" \"" + source + "\" \"System.dll\""; 
    assemblyGeneration.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
    assemblyGeneration.StartInfo.UseShellExecute = true; 
    assemblyGeneration.Start(); 
    assemblyGeneration.WaitForExit(); 
    assemblyGeneration.Dispose(); 

2.

 _appDomain.DoCallBack(() => 
     { 
      byte[] fileContent = File.ReadAllBytes(AppDomain.CurrentDomain.BaseDirectory + "script.dll"); 
      AppDomain.CurrentDomain.Load(fileContent); 
     }); 

3.

MethodInfo info = _compiledScript.GetTypeFrom("LSCT.ScriptClass").GetMethod("DefineX"); 

     var func = (Func<double>) Delegate.CreateDelegate(typeof(Func<double>), info); 
     double x = func(); 
     Console.WriteLine("Output was : " + x); 

4.

AppDomain.Unload(_appDomain); 

Donc, y a-t-il un moyen de contourner le problème, que je ne peux pas recharger la DLL?

Répondre

0

Je pense que j'ai résolu le problème. Peut-être qu'il y a un problème de performance maintenant mais je ne l'ai pas encore vérifié.

Quoi qu'il en soit, j'ai créé une nouvelle classe qui hérite de MarshalByRefObject et le laisse charger à partir du temp AppDomain.

Voici le code pour la nouvelle classe:

public class ProcessRunner : MarshalByRefObject 
{ 
    public void Run() 
    { 
     Type typ = null; 
     foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) 
     { 
      Type t = asm.GetType("LSCT.ScriptClass"); 
      if (t != null) 
      { 
       typ = t; 
       break; 
      } 
     } 
     MethodInfo info = typ.GetMethod("DefineX"); 

     var func = (Func<double>)Delegate.CreateDelegate(typeof(Func<double>), info); 
     double x = func(); 
     Console.WriteLine("Output was : " + x); 
    } 
} 

Et voici comment l'invoquer de la température AppDomain:

 ProcessRunner pr = (ProcessRunner)_appDomain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().Location, "Animation_Engine.UserInterface.Code.ProcessRunner"); 
     pr.Run(); 

Note: Dès que vous passez des références de votre AppDomain principal (par exemple par les paramètres) à la classe en cours d'exécution, la DLL sera liée à votre AppDomain principal et ne pourra pas être déchargée avant la fin du domaine principal AppDomain.