2013-05-04 15 views
8

Sto provando a fare l'applicazione con i plugin.FileNotFound quando si carica l'assembly con dipendenza in un altro dominio

Ho MainLib.dll, dove ho fatto qualche interfaccia di comando (lascia che sia ICommon) con 1 metodo. Quindi, ho creato 2 .dll (plugin) che hanno riferimento a MainLib.dll e implementano lo ICommon in alcune classi. Inoltre, ho rimosso tutti i riferimenti in questo .dlls escluso System.

Poi, ho creato un'applicazione che monitora cartella ".\\Plugins" e carica tutti dll in newDomain, verificare se i tipi di dll implementano ICommon (quindi questa applicazione anche riferimento a MainLib.dll). Se sì, aggiungi il nome di .dll in qualche elenco.

Ed ora ecco il problema: prima ho cercato di caricare i plugin - I caricare MailLib.dll e di sistema per NEWDOMAIN perché tutti i plugin hanno la dipendenza di questa DLL. Caricare correttamente. Poi, ho iniziare a caricare i plugin, e qui ho:

FileNotFoundException, Impossibile caricare il file o l'assembly 'PluginWithException, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null' o una delle sue dipendenze. Il sistema non riesce a trovare il file specificato.) Sulla stringa Assembly loadedAssembly = domain.Load (Assembly.LoadFrom (asm) .FullName);

L'assembly PluginWithException ha solo 2 dipendenze - Sistema e MainLib. Prima di provare a caricare PluginWithException, ho controllato gli assembly nel nuovo dominio, System e MainLib sono stati caricati su questo dominio. Quindi non riesco a vedere alcun ploblemi con dipendenza. Ho letto l'argomento this e ho provato la soluzione con ProxyDomain ma l'eccezione è la stessa.

Cosa sto facendo male?

Ecco il codice:

public static List<string> SearchPlugins(string[] names) 
{ 
    AppDomain domain = AppDomain.CreateDomain("tmpDomain"); 
    domain.Load(Assembly.LoadFrom(@".\MainLib.dll").FullName); 
    domain.Load(@"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 
    MessageBox.Show(GetAssembies(domain)); // here I can see that System and MailLib exist in new domain 

    List<string> plugins = new List<string>(); 

    foreach (string asm in names) 
    { 
     Assembly loadedAssembly = domain.Load(Assembly.LoadFrom(asm).FullName); // here I have exception 

     var theClassTypes = from t in loadedAssembly.GetTypes() 
          where t.IsClass && 
            (t.GetInterface("ICommonInterface") != null) 
          select t; 
     if (theClassTypes.Count() > 0) 
     { 
      plugins.Add(asm); 
     } 
    } 
    AppDomain.Unload(domain); 
    return plugins; 
} 

risposta

6

non si specifica come si impostano i percorsi di ricerca per i propri AppDomain in modo che possa trovare le DLL nella directory Plugin, tuttavia il problema potrebbe sembrare molto simile a quello che ho risposto ieri:

AppDomain.Load() fails with FileNotFoundException

Forse anche questo risolverà il problema? Fammi sapere come vai.

+0

Grazie! La tua risposta è molto utile! La soluzione con app.config funziona, ma entrambi sappiamo che questo non è il modo migliore. Ho provato la soluzione con Loader, ha eseguito il codice 'var plugins = loader.LoadPlugins ( Assembly.LoadFrom (Environment.CurrentDirectory + @" \ Plugins \ PluginWithOutException.dll "). FullName);' ma non ha aiutato :(L'eccezione è la stessa :( –

+1

Hai provato a configurare un PrivateBinPath per il figlio AppDomain durante la sua creazione, in modo che sappia cercare nella cartella Plugin gli assembly? 'Var appDomainSetup = new AppDomainSetup {PrivateBinPath =" Plugins "}; var domain = AppDomain.CreateDomain ("tmpDomain", AppDomain.CurrentDomain.Evidence, appDomainSetup); ' –

+0

Grazie! Ho provato la soluzione con' PrivateBinPath' prima, ma ho sbagliato, ora funziona e funziona bene. caricare gli assembly nei nuovi domini, chiamare il metodo dell'interfaccia e scaricare i domini, ho controllato gli assembly nel dominio corrente (predefinito) e, sfortunatamente, sono stati caricati nella corrente (d efault) dominio. E la soluzione con app.config senza Loader carica anche gli assembly nel dominio predefinito. È davvero possibile non caricare questo assembly nel dominio predefinito? –

2

si potrebbe voler dire al dominio in cui caricare gli assembly da:

AppDomain domain = AppDomain.CreateDomain("tmpDomain", null, new AppDomainSetup { ApplicationBase = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugins") });

Tuttavia, non vedo il motivo per cui si sta caricando assemblee nel dominio corrente (predefinito) e anche in tmpDomain.

+1

Grazie, ho provato il codice, ma l'eccezione è la stessa, nella stessa riga. Il mio obiettivo non è caricare gli assembly nel dominio predefinito perché non voglio mantenere l'immondizia nell'applicazione (immagine se, saranno oltre 100 plugin), quindi posso caricare alcuni plugin, usarlo e buttarlo via dall'applicazione, quando Non ne ho bisogno –

+1

OK - ma quando si esegue 'Assembly.LoadFrom (asm)' verrà caricato nel dominio corrente. Questo sconfigge il tuo scopo. Suggerisco di avere una classe personalizzata 'PluginLoader' e di caricare quella classe in tmpDomain. Quindi puoi scrivere il codice in quella classe per caricare tutti i plugin usando 'Assembly.LoadFrom' e restituire un elenco di plug-in che desideri. – YK1

+0

utilizzando sysinternals process explorer: puoi trovare ciò che viene caricato in quale dominio in qualsiasi momento. – YK1

Problemi correlati