DLR — это дополнительная обложка, написанная на C#, предназначенная для интерпретации скриптовых языков. Среди пионеров — IronPython и IronRuby. Теоретически, можно добавить любой другой интерпретируемый язык, сделав его совместимым с библиотеками .NET. Так как я чувствую в этом некоторый потенциал к расширяемости приложений, то решил изучить этот момент. В большинстве статей сделано описание того, как просто стало писать приложения на скриптовых языках, используя при это .NET библиотеки. Для меня более ценным кажется обратная возможность — запуск и управление скриптом из C# (Script Hosting).
Последнее время, стало модно выпускать различные beta и preview версии библиотек. Хорошие идеи быстро подхватываются сообществами и блогеры начинают строчить тонны текста с примерами кода. Но через некоторое время выходит окончательный релиз, с большим количеством рефакторинга, после чего примеры и описанные способы перестают работать. А блоги с устаревшей информацией продолжают нравится гуглу, окончательно запутывая программиста исследователя.
Хоть основная работа по DLR и IronPython завершена, некоторые изменения в API все еще ожидаются. На данный момент, самым исчерпывающим и достоверным источником на мой взгляд является официальная спецификация DLR (на поставленный вопрос отвечает dlr-spec-hosting.pdf)
Установка
Я пользуюсь экспресс версией Visual C# 2010. Потребовалось некоторое время, чтобы понять какие DLL мне нужны. Для начала, нужно скачать и установить какой-нибудь IronЧтото. Так как я больше знаком с питоном, поставил IronPython. Никаких новых библиотек в GAC или шаблонов в студию мне это не дало. Зато все нужные библиотеки расположились в папке приложения: Microsoft.Scripting и IronPython. Добавляем их в ссылки проекта.
Чтобы облегчить конфигурирование языков, предусмотрена конфигурационная секция. Мой App.Config выглядит следующим образом:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="microsoft.scripting" requirePermission="false" type="Microsoft.Scripting.Hosting.Configuration.Section, Microsoft.Scripting"/> </configSections> <microsoft.scripting> <languages> <language extensions=".py" displayName="IronPython 2.6.1" type="IronPython.Runtime.PythonContext, IronPython" names="IronPython;Python;py"/> </languages> </microsoft.scripting> </configuration>
И мои два тестовых файла:
Program.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Scripting.Hosting; namespace ConsoleDLR { public class MyContext { // получение переменной // если переменная Private, интерпретатор скажет, что она отсутствует. public string name = "name"; // метод для вызова из python public void Bye() { Console.WriteLine("byebye"); } } class Program { // точка входа static void Main(string[] args) { // читаем конфигурационную секцию var scriptRuntime = ScriptRuntime.CreateFromConfiguration(); // добавляем глобальный объект scriptRuntime.Globals.SetVariable("obj", new MyContext()); // загрузка файла, в нашем случае работает также как и ExecuteFile var scope = scriptRuntime.UseFile("hello.py"); // вызвать функцию их файла scriptRuntime.Operations.Call(scope.GetVariable("hello")); // инстанцировать файл и вызвать его методы var helloInstance = scriptRuntime.Operations.CreateInstance(scope.GetVariable("Hello")); helloInstance.hello(); helloInstance.tt(new MyContext()); Console.Read(); } //подобие dir() public static void ListVariables(ScriptScope scope) { foreach (string id in scope.GetVariableNames()) { dynamic fun; bool got_fun = scope.TryGetVariable(id, out fun); if (got_fun) { Console.WriteLine(id + " " + fun); } } } } }
И, соответственно «hello.py» (в свойствах укажите, чтобы студия скопировала его в bin папку):
# импорт глобального объекта. иначе скрипт о нем не знает import obj # функция для вызова def hello(): print "def world" # класс для инстанцирования class Hello: def __init__(self): print "class init" def hello(self): print "class hello" def tt(self, obj): obj.Bye() print dir(obj) print obj.name # это выполнится в самом начале print "Hello world" print obj
Теперь все готово. На выходе получается
Hello world <ConsoleDLR.MyContext object at 0x000000000000002B [ConsoleDLR.MyContext]> def world class init class hello byebye ['Bye', '__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', ' __setattr__', '__sizeof__', '__str__', '__subclasshook__', 'name'] name
Это только маленькая часть того, как можно работать с DLR. В спецификации описано большое количество, запутанных на первый взгляд, приемов. Лично я привык делать так, как быстрей и проще. Надеюсь я помог не запутаться в начале его изучения.
Метки:C#, Microsoft, разработка, Python
Похожие статьи
- 23 сентября 2011 -- Конфигурационные секции. Web.config и App.config для «C# продолжающих». (0)
- 30 декабря 2008 -- Создаем ASHX хендлер в ASP.NET (1)
- 6 февраля 2009 -- Загрузка Flash в Windows.Forms и WPF. (2)
- 18 декабря 2008 -- Транслитерация RUS 2 LAT на C# (22)
- 15 сентября 2011 -- Еще раз о работе со службами (Windows Service) на C# (0)