2012-11-18 8 views
5

Ich bin ein Skript-Engine basierend auf Roslyn in meine Anwendung eingebettet und fing an, einige Probleme zu begegnen. Wenn eine Referenz in meinen Motor Laden, ich die folgendenAssembly nicht zur Laufzeit beim Ausführen eines Roslyn-Skript gefunden

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

Fragen: ist

  1. Wenn MyAssemblyLocation Montag andere Baugruppen Referenzierung, wie kann ich feststellen, Roslyn sie zu laden, ohne dass ein engine.AddReference("MyAssemblyLocation");
  2. zu tun Die Host-Anwendung, in der das Skript ausgeführt werden soll, hat bereits einige Assemblys geladen, die ich gerne im Skript verwenden würde. Gibt es eine Möglichkeit für Roslyn, sich in die bereits geladenen dlls im Speicher einzuklinken und keine neuen Instanzen zu laden? Schließlich
  3. , ist es eine Möglichkeit, Roslyn zu sagen, rekursiv alle Abhängigkeiten laden von MyAssemblyLocation

Danke.

Antwort

6

1) Kurze Antwort: Sie müssen AddReference für alle Assemblies angeben, deren Typen Sie im Skript verwenden möchten.

Details: Der C# -Compiler rät nicht, wo die abhängigen Dateien sind. Eine Assemblydatei gibt keine vollständigen Pfade zu allen Abhängigkeiten an. Es enthält nur ihre Namen und das ist in der Regel nicht genug, damit der Compiler die Assemblydatei finden kann.

Weitere Details: Es gibt zwei Arten von Abhängigkeiten. Ich nenne sie Kompilierzeitabhängigkeiten (a) und Laufzeitabhängigkeiten (b).

(a) Angenommen, Sie haben "öffentliche Klasse A: B {}" in Assembly A.dll, "öffentliche Klasse B {}" in Assembly B.dll, und Ihr Skript verwendet A, sagen Sie ein neues erstellen Beispiel: "new A()". Der Compiler erfordert, dass Sie in diesem Fall Verweise auf A.dll und B.dll hinzufügen, da A von B abgeleitet ist und der Compiler die Vererbungshierarchie jedes verwendeten Typs analysieren muss. B. DLL ist eine kompilierzeitabhängige Abhängigkeit von Ihrem Skript - der Compiler benötigt es, um Ihr Skript richtig zu analysieren.

(b) Betrachten Sie ein anderes Beispiel: "öffentliche Klasse A {öffentliches Objekt M() {return new B();}}" in A.dll und die gleiche B.dll wie oben. Beim Kompilieren von "new A(). M()" muss der Compiler nun nicht über B Bescheid wissen, da der Verweis auf B nur im Körper der Methode M auftritt und der Compiler keine Körper von importierten Methoden analysiert. In diesem Fall reicht es aus, einen Verweis auf A.dll hinzuzufügen, um das Skript zu kompilieren. Wenn das Skript ausgeführt wird, ruft es Methode M auf. An diesem Punkt lädt die CLR Assembly B. Das wird ein bisschen komplex, also überspringe ich Details, aber in üblichen Szenarien können wir die Assembly für Sie lokalisieren, t muss den Verweis explizit hinzufügen.

2) Ich würde empfehlen, die Überladung von AddReference, die Assembly-Objekt verwendet. Etwas wie: engine.AddReference (typeof (SomeTypeInAssemblyFoo) .Assembly) zum Laden der Assembly Foo, die den Typ SomeTypeInAssemblyFoo enthält.

3) Nicht einfach. Sie können alle Referenzen, die Reflection- oder Roslyn-APIs verwenden, auflisten und jeden einzelnen davon laden.

Fühlen Sie sich frei, weitere Fragen zu stellen, wenn die Erklärung nicht klar ist oder Sie mehr Details wissen möchten.

+0

Ausgezeichnete Antwort, +1! – GETah

Verwandte Themen