2009-03-31 7 views
2

Я разрабатываю приложение, написанное на C#, на котором размещается IronPython. Я планирую, что пользователи будут писать сценарии python, которые содержат классы, реализующие предопределенный интерфейс.Запрос скриптов IronPython для интерфейсов в размещенной среде

Что-то вроде:

Определение интерфейса в C# код:

public interface IPlugin 
{ 
    void DoSomething(); 
} 

Реализовать интерфейс в питона кода.

class Plugin(IPlugin): 

     def DoSomething(): 
      print "Doing stuff." 

В моем приложении, я загрузить сценарий питона и выполнить методы, реализованные с помощью классов в этих сценариях.

Я хочу знать: как мне получить дескриптор всех классов, реализующих указанный интерфейс в скрипте python?

Например: если бы я сделать все это в C#, у меня есть отражение, чтобы помочь мне, и я могу торчат загрузить сборку и идти что-то вроде:

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 
      } 
     } 
    } 

Как сделать то же самое, когда вместо сборки я имею дело с скриптом IronPython? Я знаю, что используя ObjectOperations и ScriptScope, я могу получить дескриптор класса, если знаю его имя - as described here - но я ищу что-то более надежное.

ответ

3

Проблема заключается в том, что классы IronPython не являются классами .NET. Классы Python гораздо более динамичны, чем классы C#, поэтому классы IronPython обычно являются объектами .NET.

Когда вы подклассифицируете .NET-интерфейс в IronPython, он делает, создавая новый .NET-класс, но несколько классов Python фактически будут использовать поддерживающий .NET-класс (для каждого типа .NET будет создан только один .NET-класс подклассы в IronPython).

Правильный способ сделать это - использовать интроспекцию Python для сбора объектов класса IronPython и использовать заводскую функцию (которую вы можете использовать в качестве делегата - отбрасывание возвращаемого экземпляра в интерфейс), где вам необходимо создать экземпляр.

Например, вы можете попробовать выполнения в рамках Python:

list_of_classes = IPlugin.\_\_subclasses_\_ 
1

Динамические Языки обычно не использовать интерфейсы, вы думаете, в очень статически типизированных образом :)

Вместо того, чтобы беспокоиться, соответствует ли он какой-то предустановленный интерфейс, вы, вероятно, следует просто вызвать функцию-член и просто справиться с каким-либо заброшенным исключением - вам все равно придется иметь дело с ошибками, просто сделайте «не соответствует ожидаемому вызову метода», чтобы быть еще одним. В Objective-C это будет называться «неофициальным протоколом».

+0

Согласовано, за исключением того, что Рохит можете использовать интерфейс, чтобы различать между классами, которые он хочет, чтобы позвонить и вспомогательные классы. – Greg

+0

Да, Грег говорил мне. – Rohit

+0

Но он хочет использовать этот объект Python * from * статически типизированный язык, где он * делает *, чтобы иметь возможность различать по типу. – fuzzyman

0

Согласно FAQ IronPython он не поддерживает компиляцию * .py файлов в сборку, которая затем может быть связан с:

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

Но Павел правильно, если вы собираетесь использовать динамический язык для такого рода расширяемости, который вы хотите сделать так же просто, как просто редактировать файл, а не понимать интерфейсы из среды выполнения.

Если вы раскрываете эту точку расширяемости для типов системного администратора, вам может потребоваться разместить PowerShell. Я написал сообщение некоторое время назад о том, как это сделать:

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

PowerShell хорош для этого, потому что он уже имеет принятие в средах, где используется обмен. Имейте в виду - я поклонник PowerShell так считать, что с зерном соли :)

+0

Ответ на часто задаваемые вопросы, которые вы указываете мне, также говорит: «вы можете определить интерфейсы на C#, собрать их в DLL, а затем реализовать эти интерфейсы в коде Python, а также передать объекты python, которые реализуют интерфейсы для кода C#». Как это сделать, я ищу. – Rohit

+0

Это легко. После того, как код C# скомпилирован в DLL, вам нужно только clr.AddReference («YourAssembly.dll»), а затем вы можете создавать экземпляры в нем. –

1

Вы всегда можете получить тип поддержка .NET для типа Python, вызвав clr.GetClrType

Python.GetClrModule (двигатель) возвращает модуль clr, а затем вызывает метод GetClrType на нем, проходящий в классе Python, который вы получили с помощью объектных операций. Это должно вернуть вам System.Type. После этого используйте метод GetInterfaces, как обычно.

+0

Итак, я должен делать scope.GetItems() и вызывать метод GetClrType для каждого возвращаемого значения? Правильно ли это? – Rohit