2010-06-09 11 views
6

Ich versuche, IronPython als Vermittler zwischen einer C# -GUI und einigen C# -Bibliotheken zu verwenden, so dass es nach der Kompilierungszeit geschrieben werden kann.C#/IronPython Interop mit freigegebener C# -Klassenbibliothek

Ich habe eine Klassenbibliothek DLL, die sowohl von der GUI und der Python verwendet wird, und ist etwas entlang der Linien von dieser:

namespace MyLib 
{ 
    public class MyClass 
    { 
     public string Name { get; set; } 
     public MyClass(string name) 
     { 
      this.Name = name; 
     } 
    } 
} 

Der Ironpython-Code wird wie folgt dar:

import clr 
clr.AddReferenceToFile(r"MyLib.dll") 
from MyLib import MyClass 

ReturnObject = MyClass("Test") 

dann wird in C# würde ich es nennen wie folgt:

ScriptEngine engine = Python.CreateEngine(); 
ScriptScope scope = null; 

scope = engine.CreateScope(); 
ScriptSource source = engine.CreateScriptSourceFromFile("Script.py"); 

source.Execute(scope); 

MyClass mc = scope.GetVariable<MyClass>("ReturnObject ") 

als ich dieses letzte Stück Code nennen, source.Ex ecute (scope) läuft kehrt erfolgreich, aber wenn ich den GetVariable Anruf versuchen, werfen sie die folgende Ausnahme

Microsoft.Scripting.ArgumentTypeException: expected MyClass , got MyClass 

So können Sie sehen, dass die Klassennamen sind genau die gleichen, aber aus irgendeinem Grund es denkt, sie sind anders.

Die DLL befindet sich in einem anderen Verzeichnis als die .py-Datei (ich habe mir einfach nicht die Mühe gemacht, alle Pfad-Setup-Sachen zu schreiben), könnte es sein, dass es ein Problem mit dem Interpreter für IronPython gibt Unterschied, weil es sie irgendwie in einem anderen Kontext oder Bereich sieht?

Antwort

11

Dieser Fehler weist darauf hin, dass Ihre Assembly in mehrere CLR Loader-Kontexte geladen wird. Anstatt den Verweis mithilfe von clr.AddReferenceToFile hinzuzufügen, können Sie entweder zu clr.AddReference wechseln oder Sie können die Assembly aus C# laden. Bei ersterem müssen Sie sicherstellen, dass die Assembly irgendwo verfügbar ist, wo .NET sie normalerweise laden kann (der GAC oder in der Anwendungsbasis des Prozesses). Für letzteres können Sie einfach tun:

engine.Runtime.LoadAssembly(typeof(MyClass).Assembly); 

von Ihrem C# -Host-Code. Persönlich mag ich diese zweite Lösung ein bisschen mehr, weil es nicht nur funktioniert, sondern es Ihren Benutzern erspart, den clr.AddRef-Aufruf von Python zu machen.

1

Sie könnten versuchen, Ihr Programm unter dem Debugger auszuführen und die Ausführung vor dem GetVariable-Aufruf zu unterbrechen. Wechseln Sie zum Fenster "Module", und prüfen Sie, ob zwei Versionen Ihrer DLL für die C# -Klassenbibliothek geladen sind. Wenn das der Fall ist, dann ist das die Erklärung.

Wenn das das Problem ist, dann ist die Lösung sicherzustellen, dass C# - und Python-Welten den Typen zustimmen. Eine Lösung besteht darin, alles in das gleiche Verzeichnis zu stellen. Eine andere Möglichkeit besteht darin, einen Verweis auf Ihre Klassenbibliothek in C# einzurichten, indem Sie die Eigenschaften der ScriptScope-Klasse verwenden, um einen Assemblyverweis auf Ihre Klassenbibliotheksassembly zu setzen, die für den Python-Code verfügbar ist. Ich habe kein hybrides C#/IronPython-Projekt, das sofort getestet werden kann, aber ich erinnere mich, dass ich diese Funktionalität gesehen habe.