2012-11-18 7 views
5

Inserisco un motore di script basato su Roslyn nella mia applicazione e ho iniziato ad affrontare alcuni problemi. Quando si carica un riferimento nel mio motore, faccio la seguenteAssemblaggio non trovato in fase di esecuzione durante l'esecuzione di uno script Roslyn

var engine = new Roslyn.Scripting.CSharp.ScriptEngine(); 
engine.AddReference("MyAssemblyLocation"); 

Domande:

  1. Se MyAssemblyLocation montaggio fa riferimento altre assemblee, come faccio a dire Roslyn caricarli senza fare un engine.AddReference("MyAssemblyLocation");
  2. L'applicazione host in cui si suppone che lo script sia in esecuzione ha già caricato alcuni assembly che vorrei utilizzare nello script, c'è un modo per Roslyn di collegarsi alle DLL già caricate in memoria e non caricare nuove istanze?
  3. Infine, c'è un modo per dire a Roslyn per caricare in modo ricorsivo tutte le dipendenze di MyAssemblyLocation

Grazie.

risposta

6

1) Risposta breve: è necessario aggiungereRiferimento su tutti gli assembly di cui si intende utilizzare i tipi nello script.

Dettagli: Il compilatore C# non indovina dove sono i file dipendenti. Un file assembly non specifica percorsi completi per tutte le sue dipendenze. Contiene solo i loro nomi e in genere non è sufficiente per consentire al compilatore di individuare il file di assembly.

Ulteriori dettagli: Esistono due tipi di dipendenze. Li chiamerò dipendenze del tempo di compilazione (a) e delle dipendenze di runtime (b).

(a) Supponiamo di avere "public class A: B {}" nell'assembly A.dll, "public class B {}" nell'assembly B.dll e lo script utilizza A, ad esempio si crea un nuovo esempio: "nuova A()". Il compilatore richiede in questo caso l'aggiunta di riferimenti ad A.dll e B.dll, poiché A deriva da B e il compilatore deve analizzare la gerarchia di ereditarietà di ciascun tipo che si utilizza. Quindi B.dll è una dipendenza in fase di compilazione del tuo script - il compilatore ne ha bisogno per analizzare correttamente lo script.

(b) Considerare un altro esempio: "public class A {oggetto pubblico M() {return new B();}}" in A.dll e lo stesso B.dll come sopra. Ora quando si compila "nuovo A(). M()" il compilatore non ha bisogno di sapere di B, poiché il riferimento a B si verifica solo nel corpo del metodo M e il compilatore non analizza i corpi dei metodi importati. In questo caso è sufficiente aggiungere un riferimento a A.dll per compilare lo script. Quando lo script viene eseguito chiama il metodo M. A quel punto il CLR carica l'assembly B. Questo diventa un po 'complesso, quindi salterò i dettagli ma negli scenari comuni saremo in grado di localizzare l'assembly per te, quindi non lo farai t necessario aggiungere esplicitamente il riferimento

2) Si consiglia di utilizzare l'overload di AddReference che richiede l'oggetto Assembly. Qualcosa come: engine.AddReference (typeof (SomeTypeInAssemblyFoo) .Assembly) per caricare l'assembly Foo che contiene type SomeTypeInAssemblyFoo.

3) Non semplice. È possibile enumerare tutti i riferimenti utilizzando le API Reflection o Roslyn e caricare ciascuno di essi.

Sentiti libero di fare ulteriori domande se la spiegazione non è chiara o se desideri conoscere maggiori dettagli.

+0

Risposta eccellente, +1! – GETah

Problemi correlati