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)

