2009-03-31 12 views
2

Je développe une application écrite en C# qui héberge IronPython. Ce que je prévois, c'est que les utilisateurs vont écrire des scripts Python, qui contiennent des classes implémentant une interface prédéfinie.Demande de scripts IronPython pour les interfaces dans un environnement hébergé

Quelque chose comme:

Define interface code C#:

public interface IPlugin 
{ 
    void DoSomething(); 
} 

implémentent l'interface en code python. Dans mon application, je charge le script python et j'exécute les méthodes implémentées par les classes dans ces scripts.

Je veux savoir: comment obtenir un handle pour toutes les classes qui implémentent l'interface spécifiée dans le script python?

Par exemple, si je devais faire tout cela en C#, je dois réfléchir pour me aider et je peux saillir charger l'assemblage et aller quelque chose comme:

Assembly assembly = Assembly.LoadFrom("plugin.dll"); 
    Type[] types = assembly.GetTypes(); 
    foreach(Type type in types) 
    { 
     foreach(Type interfaceType in type.GetInterface()) 
     { 
      if(interfaceType == typeof(IPlugin)) 
      { 
       // gotcha, invoke interface specific methods 
      } 
     } 
    } 

Comment puis-je faire la même chose, quand au lieu d'une assemblée, j'ai affaire à un script IronPython? Je sais qu'en utilisant ObjectOperations et le ScriptScope, je peux obtenir un traitement à la classe, si je connais son nom - as described here - mais je cherche quelque chose de plus robuste.

Répondre

3

Le problème que vous avez, c'est que les classes IronPython ne sont pas des classes .NET. Les classes Python sont beaucoup plus dynamiques que les classes C# donc les classes IronPython sont typiquement des objets .NET.

Lorsque vous sous-classe d'une interface .NET dans IronPython il ne créer une nouvelle classe .NET, mais plusieurs classes de Python fait partager une classe .NET de support (une seule classe .NET sera créé pour chaque type .NET sous-classé dans IronPython). La méthode correcte consiste à utiliser Python introspection pour collecter les objets de classe IronPython et utiliser une fonction factory (que vous pouvez utiliser en tant que délégué - en renvoyant l'instance renvoyée vers l'interface) où vous devez les instancier.

Par exemple, vous pouvez essayer d'exécuter dans le cadre de Python:

list_of_classes = IPlugin.\_\_subclasses_\_ 
1

Langues dynamiques ne pas utiliser généralement des interfaces, vous pensez d'une manière très statiquement typé :)

Au lieu de se soucier si elle correspond à une interface prédéfinie, vous devriez probablement appeler la fonction membre et juste Traiter toutes les exceptions levées - vous aurez à faire face à des erreurs de toute façon, faites juste "ne correspond pas à l'appel de méthode que nous attendons" pour en faire un de plus. En Objective-C, cela s'appellerait un "protocole informel".

+0

Convenu, sauf que Rohit peut vouloir utiliser l'interface pour différencier entre les classes qu'il veut appeler et classes d'aide. – Greg

+0

Oui, Greg m'a parlé. – Rohit

+0

Mais il veut utiliser ces objets Python * à partir * d'un langage typé statiquement où il * doit * être capable de différencier le type. – fuzzyman

0

Selon la FAQ IronPython il ne supporte pas la compilation de fichiers * .py dans un ensemble qui pourrait ensuite être liée à:

http://ironpython.codeplex.com/Wiki/View.aspx?title=FAQ&referringTitle=Home

Mais Paul est correct, si vous allez utiliser un langage dynamique pour ce genre d'extensibilité, vous voulez le rendre aussi simple que de modifier un fichier plutôt que de devoir comprendre les interfaces d'une exécution.

Si vous présentez ce point d'extension aux types d'administrateur système, vous pouvez envisager d'héberger PowerShell. J'ai écrit un message il y a un peu de temps sur la façon de le faire:

http://notgartner.wordpress.com/2008/02/23/how-to-host-the-powershell-runtime/

PowerShell est bon pour cela, car il a déjà une adoption dans des environnements où Exchange est utilisé. Rappelez-vous - je suis un fan PowerShell afin de prendre cela avec un grain de sel :)

+0

La réponse dans la FAQ que vous me pointez dit aussi "vous pouvez définir des interfaces en C#, les intégrer dans une DLL, puis implémenter ces interfaces en code Python et passer les objets python qui implémentent les interfaces au code C#". Comment faire est ce que je cherche. – Rohit

+0

C'est facile. Une fois que vous avez compilé votre code C# dans une DLL, tout ce que vous avez à faire est clr.AddReference ("YourAssembly.dll") et vous pouvez ensuite instancier les types dedans. –

1

Vous pouvez toujours obtenir le type .NET de support pour un type Python en appelant clr.GetClrType

Python.GetClrModule (moteur) renvoie le module clr, puis appelle la méthode GetClrType en passant dans la classe Python que vous avez obtenue en utilisant des opérations d'objets. Cela devrait vous renvoyer un System.Type. Après cela, utilisez la méthode GetInterfaces comme vous le feriez normalement.

+0

Donc, je devrais faire un scope.GetItems() et appeler la méthode GetClrType sur chacune des valeurs retournées? Est-ce la bonne façon? – Rohit