将列表从IronPython传递到C#

Ben*_*der 15 c# ironpython

我想将IronPython 2.6 for .NET 2.0中的字符串列表传递给C#程序(我使用的是.NET 2.0,因为我正在使用基于2.0构建的DLL运行的api).但是我不确定如何从ScriptEngine返回时抛出它.

namespace test1
{
    class Program
    {
        static void Main(string[] args)
        {
            ScriptEngine engine = Python.CreateEngine();
            ScriptSource source = engine.CreateScriptSourceFromFile("C:\\File\\Path\\To\\my\\script.py");
            ScriptScope scope = engine.CreateScope();

            ObjectOperations op = engine.Operations;

            source.Execute(scope); // class object created
            object classObject = scope.GetVariable("MyClass"); // get the class object
            object instance = op.Invoke(classObject); // create the instance
            object method = op.GetMember(instance, "myMethod"); // get a method
            List<string> result = (List<string>)op.Invoke(method); // call the method and get result
            Console.WriteLine(result.ToString());
            Console.Read();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的python代码有一个类,其方法返回一个字符串的python列表:

class MyClass(object):
    def myMethod(self):
        return ['a','list','of','strings']
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

Unable to cast object of type 'IronPython.Runtime.List' to type 'System.Collections.Generic.List`1[System.String]'.
Run Code Online (Sandbox Code Playgroud)

dig*_*All 19

IronPython.Runtime.List 实现以下接口:

IList, ICollection, IList<object>, ICollection<object>, IEnumerable<object>, IEnumerable
Run Code Online (Sandbox Code Playgroud)

所以你可以投射到其中一种类型然后变成一种List<string>.

List<string> result = ((IList<object>)op.Invoke(method)).Cast<string>().ToList();
Run Code Online (Sandbox Code Playgroud)

顺便说一下,也许您已经意识到了这一点,但您也可以在IronPython中使用.NET类型,例如:

from System.Collections.Generic import *

class MyClass(object):
    def myMethod(self):
        return List[str](['a','list','of','strings'])
Run Code Online (Sandbox Code Playgroud)

这里myMethod直接返回一个List<string>


编辑:

鉴于您使用的是.net 2.0(所以没有LINQ),您有两个选项(IMO):

1.投射IList<object>并使用它:

IList<object> result = (IList<object>)op.Invoke(method);
Run Code Online (Sandbox Code Playgroud)

PRO:不需要循环,您将使用python脚本返回的相同对象实例.
CONs:没有类型安全(你会像在python中一样,所以你也可以在列表中添加一个非字符串)

2.转换为List<string>/ IList<string>:

IList<object> originalResult = (IList<object>)op.Invoke(method);
List<string> typeSafeResult = new List<string>();
foreach(object element in originalResult)
{
    typeSafeResult.Add((string)element);
}
Run Code Online (Sandbox Code Playgroud)

PRO:类型安全列表(您只能添加字符串).
CONs:它需要一个循环,转换后的列表是一个新实例(脚本返回的不同)