从C#创建IronPython类的实例

问题描述:

我想从C#创建一个IronPython类的实例,但我目前的尝试似乎都失败了。从C#创建IronPython类的实例

这是我当前的代码:

ConstructorInfo[] ci = type.GetConstructors(); 

foreach (ConstructorInfo t in from t in ci 
           where t.GetParameters().Length == 1 
           select t) 
{ 
    PythonType pytype = DynamicHelpers.GetPythonTypeFromType(type); 
    object[] consparams = new object[1]; 
    consparams[0] = pytype; 
    _objects[type] = t.Invoke(consparams); 
    pytype.__init__(_objects[type]); 
    break; 
} 

我能够从调用t.Invoke(consparams)获取对象的创建的实例,但__init__方法似乎并没有被调用,因此我没有使用从我的Python脚本中设置的所有属性。即使调用明确的pytype.__init__,构造的对象似乎仍未被初始化。

使用ScriptEngine.Operations.CreateInstance似乎也不起作用。

我正在使用.NET 4.0与IronPython 2.6 for .NET 4.0。

编辑:小澄清如何我打算做到这一点:

在C#中,我有一个类如下:

public static class Foo 
{ 
    public static object Instantiate(Type type) 
    { 
     // do the instantiation here 
    } 
} 

而且在Python,下面的代码:

class MyClass(object): 
    def __init__(self): 
     print "this should be called" 

Foo.Instantiate(MyClass) 

__init__方法似乎永远不会被调用。

+0

可能的重复[在C#中实例化一个python类](http://*.com/questions/579272/instantiating-a-python-class-in-c) – 2010-08-04 05:11:26

+0

在看了一下IronPython的源代码后, \ __init__方法被定义为public void __init __(object o){}。哎呦。 – rfw 2010-08-04 05:16:11

该代码可以使用的IronPython 2.6.1

static void Main(string[] args) 
    { 
     const string script = @" 
class A(object) : 
    def __init__(self) : 
     self.a = 100 

class B(object) : 
    def __init__(self, a, v) : 
     self.a = a 
     self.v = v 
    def run(self) : 
     return self.a.a + self.v 
"; 

     var engine = Python.CreateEngine(); 
     var scope = engine.CreateScope(); 
     engine.Execute(script, scope); 

     var typeA = scope.GetVariable("A"); 
     var typeB = scope.GetVariable("B"); 
     var a = engine.Operations.CreateInstance(typeA); 
     var b = engine.Operations.CreateInstance(typeB, a, 20); 
     Console.WriteLine(b.run()); // 120 
    } 

EDITED根据澄清的问题

class Program 
    { 
     static void Main(string[] args) 
     { 
      var engine = Python.CreateEngine(); 
      var scriptScope = engine.CreateScope(); 

      var foo = new Foo(engine); 

      scriptScope.SetVariable("Foo", foo); 
      const string script = @" 
class MyClass(object): 
    def __init__(self): 
     print ""this should be called"" 

Foo.Create(MyClass) 
"; 
      var v = engine.Execute(script, scriptScope); 
     } 
    } 

public class Foo 
{ 
    private readonly ScriptEngine engine; 

    public Foo(ScriptEngine engine) 
    { 
     this.engine = engine; 
    } 

    public object Create(object t) 
    { 
     return engine.Operations.CreateInstance(t); 
    } 
} 
+0

问题是我没有使用'scope.GetVariable' - 我以C#'Type'类的形式直接将类型传递给C#,主要是因为我需要从各种地方调用函数并且该变量可能不一定在该范围内可用。 – rfw 2010-08-04 07:38:47

+0

即使我回答了我自己的问题,我仍然认为你应该被接受的答案:) – rfw 2010-08-04 08:23:04

看起来你正在寻找给予this SO question的答案。

+0

答案从来没有实际上说过任何关于实例化对象的东西 - 例子中的Calculator类没有构造方法,因此它没有真正回答我的问题。 – rfw 2010-08-04 05:13:56

+0

SO Q的解决方案对我来说工作正常,并且添加'__init__'方法会执行它(使用如图所示的'.Operations'实例)。我没有.NET 4.0试用版,但如果他们在4.0版本中破坏了某些东西,我会感到惊讶。 – 2010-08-04 05:35:02

+0

这个例子并不完全适合我,因为我将类型本身传递给C#代码,而不是范围变量,即通过函数,这可能是为什么不调用__init__方法。 – rfw 2010-08-04 06:29:07

我想我解决我自己的问题 - 使用.NET Type类似乎丢弃了Python类型的信息。

IronPython.Runtime.Types.PythonType取代它很好。