Использование IronRuby или IronPython для изменения списка объектов C # - PullRequest
2 голосов
/ 09 августа 2010

Если бы у меня был список объектов, например. List<Foo>, где Foo имеет несколько свойств, могу ли я тогда создать один или несколько сценариев ironruby или ironpython, которые выполняются для каждой строки.

Вот некоторый псевдокод:

var items = new List<Foo>();
foreach(var item in items) {
   var pythonfunc = getPythonFunc("edititem.py");
   item = pythonfunc(item);
}

Мне нужен динамический способ изменить список, в котором код хранится в БД или файле.

Если вы считаете, что есть лучший способ сделать это или у вас есть альтернатива для написания пользовательской подпрограммы для клиента, которая может извлекать специфичные для клиента данные из базы данных (экспорт), прокомментируйте или оставить предложение.

Спасибо

1 Ответ

4 голосов
/ 10 августа 2010

Я использовал этот подход раньше, сохраняя скрипты IronPython в базе данных и в файлах. Шаблон, который мне нравится - хранить функции Python с именами, известными по соглашению. Другими словами, если вы обрабатываете объект типа Foo, у вас может быть функция Python с именем "foo_filter" в вашем .py файле или таблице. В конечном счете, вы можете выполнить файл Python и разобрать функции в словарь ссылок на функции.

Пример приложения ...

Ваш класс foo:

public class Foo {
    public string Bar { get; set; }
}

Настройка Foo и вызов getPythonFunc (i);

var items = new List<Foo>() {
    new Foo() { Bar = "connecticut" },
    new Foo() { Bar = "new york" },
    new Foo() { Bar = "new jersey" }                    
};

items.ForEach((i) => { getPythonFunc(i); Console.WriteLine(i.Bar); });

Быстрая и грязная реализация getPythonFun ... Граф объекта ScriptXXX, очевидно, должен быть кэширован, как и переменные, полученные GetVariable ().

static void getPythonFunc(Foo foo) {

    ScriptRuntimeSetup setup = ScriptRuntimeSetup.ReadConfiguration();
    ScriptRuntime runtime = new ScriptRuntime(setup);
    runtime.LoadAssembly(Assembly.GetExecutingAssembly());
    ScriptEngine engine = runtime.GetEngine("IronPython");
    ScriptScope scope = engine.CreateScope();

    engine.ExecuteFile("filter.py", scope);

    var filterFunc = scope.GetVariable("filter_item");
    scope.Engine.Operations.Invoke(filterFunc, foo);
}

Содержимое filter.py:

def filter_item(item):
    item.Bar = item.Bar.title()

Простой способ применения правил на основе свойства (не добавление свойства Size в Foo):

var items = new List<Foo>() {
    new Foo() { Bar = "connecticut", Size = "Small" },
    new Foo() { Bar = "new york", Size = "Large" },
    new Foo() { Bar = "new jersey", Size = "Medium" }
};

Измените строку в getPythonFun (), которая вызывает GetVariable () ScriptScope:

var filterFunc = scope.GetVariable("filter_" + foo.Size.ToLower());

И новое содержимое filter.py

def filter_small(item):
    item.Bar = item.Bar.lower()

def filter_medium(item):
    item.Bar = item.Bar.title()

def filter_large(item):
    item.Bar = item.Bar.upper()

У меня есть несколько более полных образцов, доступных на http://www.codevoyeur.com/Articles/Tags/ironpython.aspx.

...