2010-06-09 6 views
6

J'essaie d'utiliser IronPython comme intermédiaire entre une interface graphique C# et certaines bibliothèques C#, afin qu'elle puisse être scriptée après la compilation.C#/IronPython Interop avec bibliothèque de classes C# partagée

J'ai une DLL de bibliothèque de classe qui est utilisée par l'interface utilisateur graphique et le python et est quelque chose le long des lignes de celle-ci:

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

Le code IronPython est comme suit:

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

ReturnObject = MyClass("Test") 

puis, en C# je qualifierais comme suit:

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 ") 

Quand j'appelle ce dernier morceau de code, source.Ex ecute (portée) court retourne avec succès, mais lorsque je tente l'appel GetVariable, il jette l'exception suivante

Microsoft.Scripting.ArgumentTypeException: expected MyClass , got MyClass 

Ainsi, vous pouvez voir que les noms de classe sont exactement les mêmes, mais pour une raison quelconque, il pense qu'ils sont différent. La DLL se trouve dans un répertoire différent de celui du fichier .py (je n'ai pas pris la peine d'écrire toutes les informations d'installation du chemin), est-ce dû au fait qu'il y a un problème avec l'interpréteur pour IronPython? différence parce que c'est en quelque sorte les voir comme étant dans un contexte ou une portée différente?

Répondre

11

Cette erreur indique que votre assembly est chargé dans plusieurs contextes de chargeur CLR. Plutôt que d'ajouter la référence à l'aide de clr.AddReferenceToFile, vous pouvez passer à clr.AddReference ou charger l'assembly à partir de C#. Pour le premier, vous devez vous assurer que l'assembly est disponible quelque part que .NET peut normalement le charger (le GAC ou dans la base d'application du processus). Pour ce dernier, vous pouvez simplement faire:

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

à partir de votre code hôte C#. Personnellement, j'apprécie un peu plus cette deuxième solution car non seulement cela fonctionne, mais cela évite à vos utilisateurs d'avoir à faire l'appel clr.AddRef de Python.

1

Vous pouvez essayer d'exécuter votre programme sous le débogueur et de casser l'exécution avant l'appel GetVariable. Allez dans la fenêtre "modules" et voyez s'il y a deux versions de votre DLL de bibliothèque de classe C# chargée. Si c'est le cas, alors c'est l'explication.

Si c'est le problème, alors la solution est de s'assurer que les mondes C# et Python sont d'accord sur les types. Une solution consiste à tout mettre dans le même répertoire. Une autre possibilité est de configurer une référence à votre bibliothèque de classes en C# en utilisant les propriétés de la classe ScriptScope (je pense) pour définir une référence d'assembly à votre assembly de bibliothèque de classes qui sera disponible pour le code Python. Je n'ai pas de projet hybride C#/IronPython immédiatement disponible pour tester, mais je me souviens avoir vu cette fonctionnalité.