开发者

Creating Instances of IronPython Classes From C#

开发者 https://www.devze.com 2023-01-10 07:24 出处:网络
I want to create an instance of an IronPython class from C#, but my current attempts all seem to have failed.

I want to create an instance of an IronPython class from C#, but my current attempts all seem to have failed.

This is my current code:

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

I am able to get the created instance of the object from calling t.Invoke(consparams), but the __init__ method doesn't seem to be called, and thus all the properties that I set from my Python script aren't used. Even with the explicit pytype.__init__ call, the constructed object still doesn't seem to be initialised.

Using ScriptEngine.Operations.CreateInstance doesn't seem to work, either.

I'm using .NET 4.0 with IronPython 2.6 for .NET 4.0.

EDIT: Small clarification on how I'm intending to do this:

In C#, I have a class as follows:

public static class Foo
{
    public static object Instantiate(Type type)
    {
        // do the instantiation here
   开发者_JAVA技巧 }
}

And in Python, the following code:

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

Foo.Instantiate(MyClass)

The __init__ method never seems to be called.


This code works with 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 according to clarified question

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


I think I solved my own question -- using the .NET Type class seems to have discarded Python type information.

Replacing it with IronPython.Runtime.Types.PythonType works quite well.


Looks like you're looking for the answer given to this SO question.

0

精彩评论

暂无评论...
验证码 换一张
取 消