简体   繁体   中英

How to invoke C#/.NET namespace in IronPython?

I'm looking to replicate the following in IronPython and searching has so far been fruitless and/or disappointing.

namespace Groceries
{
     public class ChocolateMilk : Milk
     {
          // Other stuff here
     }
}

The idea would be that the compiled Python DLL will be loaded into a C# program through System.Reflection.Assembly.Load and a GetType("Groceries.ChocolateMilk") on the loaded DLL would not return null.

The most recent answer I was able to find was in 2008 and said that it was impossible without using the Hosting API - http://lists.ironpython.com/pipermail/users-ironpython.com/2008-October/008684.html .

Any suggestions on how to accomplish this would be greatly appreciated. Any conclusions that this is currently impossible to do via IronPython will also be appreciated, but less so.

I'm a bit confused on what you're asking here. Are you trying to instantiate that C# code in your IronPython modules? Or do you have the equivalent classes written in IronPython and you want to instantiate them in your C# code?

Based on the link you posted, I suppose you're going for the latter and have IronPython classes that you want instantiated in your C# code. The answer is, you cannot directly instantiate them. When you compile IronPython code to an assembly, you cannot use the types defined there with your regular .NET code since there is not a one-to-one mapping between IronPython classes and .NET classes. You would have to host the assembly in your C# project and instantiate it that way.

Consider this module, Groceries.py compiled to Groceries.dll residing in the working directory:

class Milk(object):
    def __repr__(self):
        return 'Milk()'

class ChocolateMilk(Milk):
    def __repr__(self):
        return 'ChocolateMilk()'

To host the module in your C# code:

using System;

using IronPython.Hosting;
using System.IO;
using System.Reflection;

class Program
{
    static void Main(string[] args)
    {
        var engine = Python.CreateEngine();
        var groceriesPath = Path.GetFullPath(@"Groceries.dll");
        var groceriesAsm = Assembly.LoadFile(groceriesPath);
        engine.Runtime.LoadAssembly(groceriesAsm);

        dynamic groceries = engine.ImportModule("Groceries");
        dynamic milk = groceries.ChocolateMilk();
        Console.WriteLine(milk.__repr__()); // "ChocolateMilk()"
    }
}

Otherwise to go the other way and create an instance of your .NET type in your IronPython code (as your title suggests). You'd need to add the path to your assembly, reference it, then you could instantiate it as needed.

# add to path
import sys
sys.path.append(r'C:\path\to\assembly\dir')

# reference the assembly
import clr
clr.AddReferenceToFile(r'Groceries.dll')

from Groceries import *
chocolate = ChocolateMilk()
print(chocolate)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM