查询托管环境中接口的IronPython脚本

时间:2009-03-31 05:11:11

标签: .net ironpython dynamic-language-runtime

我正在开发一个用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,我可以获得该类的句柄,如果我知道它的名字 - as described here - 但我正在寻找更强大的东西。

4 个答案:

答案 0 :(得分:3)

您遇到的问题是IronPython类不是.NET类。 Python类比C#类更具动态性,因此IronPython类通常是.NET对象。

当您在IronPython中继承.NET接口时,它 创建一个新的.NET类,但是多个Python类实际上将共享一个支持.NET类(将只创建一个.NET类用于在IronPython中子类化的每个.NET类型。)

执行此操作的正确方法是使用Python内省来收集IronPython类对象,并使用工厂函数(可以将其用作委托 - 将返回的实例强制转换为接口),您需要在其中实例化它们。 / p>

例如,您可以尝试在Python范围内执行:

list_of_classes = IPlugin.\_\_subclasses_\_

答案 1 :(得分:1)

动态语言通常不使用接口,您正在以非常静态的方式思考:)

不应该担心它是否与某个预定义的接口相匹配,你应该只调用成员函数并处理抛出的任何异常 - 无论如何你都必须处理错误,只需要“不适合方法调用我们期待“再多一点。在Objective-C中,这将被称为“非正式协议”。

答案 2 :(得分:1)

通过调用clr.GetClrType

,您始终可以获得Python类型的支持.NET类型

Python.GetClrModule(engine)返回clr模块,然后在其上调用GetClrType方法,传递使用objectoperations获取的Python类。这应该会给你一个System.Type。之后,像往常一样使用GetInterfaces方法。

答案 3 :(得分:0)

根据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的粉丝,所以请一点点盐:)