передача списков из IronPython в C # - PullRequest
15 голосов
/ 06 марта 2011

Я хочу передать список строк из IronPython 2.6 для .NET 2.0 в программу на C # (я использую .NET 2.0, потому что я работаю с API, работающим на DLL, созданных на основе 2.0). Но я не уверен, как его разыграть, поскольку он возвращается из 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();
        }
    }
}

В моем коде Python есть класс с методом, который возвращает список строк Python:

class MyClass(object):
    def myMethod(self):
        return ['a','list','of','strings']

Я получаю эту ошибку:

Unable to cast object of type 'IronPython.Runtime.List' to type 'System.Collections.Generic.List`1[System.String]'.

Ответы [ 2 ]

18 голосов
/ 06 марта 2011

IronPython.Runtime.List реализует следующие интерфейсы:

IList, ICollection, IList<object>, ICollection<object>, IEnumerable<object>, IEnumerable

, так что вы можете привести к одному из этих типов и затем превратиться в List<string>.

List<string> result = ((IList<object>)op.Invoke(method)).Cast<string>().ToList();

Кстати, возможно, вы знаете об этом, но вы также можете использовать типы .NET в IronPython, например ::1010*.

from System.Collections.Generic import *

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

здесь myMethod возвращает непосредственно List<string>


EDIT:

Учитывая, что вы используете .net 2.0 (поэтому нет LINQ), у вас есть два варианта (IMO):

1. Приведите к IList<object> и используйте его:

IList<object> result = (IList<object>)op.Invoke(method);

PROs : цикл не требуется, вы будете использовать тот же экземпляр объекта, который возвращается скриптом 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);
}

PROs : введите безопасный список (вы можете добавить только строки).
CONs : требуется цикл, и преобразованный список является новым экземпляром (не тем, который возвращается скриптом)

1 голос
/ 06 марта 2011

Вы можете использовать IList на стороне C #, и IronPython автоматически обернет объект List в оболочку, которая выполняет преобразование в / из строки при доступе к списку.

...