Запрос сценариев IronPython для интерфейсов в размещенной среде - PullRequest
2 голосов
/ 31 марта 2009

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

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

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

public interface IPlugin
{
    void DoSomething();
}

Реализация интерфейса в коде Python.

class Plugin(IPlugin):

      def DoSomething():
          print "Doing stuff."

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

Я хочу знать: как мне получить дескриптор всех классов, которые реализуют указанный интерфейс в скрипте 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, я могу получить дескриптор класса, если знаю его имя - , как описано здесь - но я ищу что-то более надежное.

Ответы [ 4 ]

3 голосов
/ 01 апреля 2009

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

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

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

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

list_of_classes = IPlugin.\_\_subclasses_\_
1 голос
/ 31 марта 2009

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

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

1 голос
/ 31 марта 2009

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

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

0 голосов
/ 31 марта 2009

Согласно 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 хорош для этого, потому что он уже получил некоторое распространение в средах, где используется Exchange. Имейте в виду - я фанат PowerShell, поэтому возьмите это с крошкой соли:)

...