2

我正在开发一个用 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

4 回答 4

3

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

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

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

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

list_of_classes = IPlugin.\_\_subclasses_\_
于 2009-04-01T01:12:58.457 回答
1

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

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

于 2009-03-31T05:15:12.063 回答
1

您始终可以通过调用 clr.GetClrType 来获取 Python 类型的支持 .NET 类型

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

于 2009-03-31T18:04:34.303 回答
0

根据 IronPython FAQ,它不支持将 *.py 文件编译成可以链接到的程序集:

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

但 Paul 是对的,如果你打算使用动态语言来实现这种可扩展性,你会希望让它像编辑文件一样简单,而不必从运行时理解接口。

如果您将此可扩展点公开给系统管理员类型,您可能需要考虑托管 PowerShell。不久前我写了一篇关于如何做到这一点的帖子:

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

PowerShell 对此有好处,因为它已经在使用 Exchange 的环境中得到了一些采用。请注意 - 我是 PowerShell 的粉丝,所以请谨慎对待 :)

于 2009-03-31T05:37:29.873 回答