Несколько лет назад я был на 100% программистом под .NET. Я представления не имел об остальном мире разработки и был весьма счастлив в своей раковине. Потом — скорее всего по ошибке — я изучил Ruby, и открывшийся мир оказался просто обалденным. То, что можно было делать, используя встроенные языковые средства, просто поразило меня.
Изъять человека из мира .NET можно, но изъять мир .NET из него нельзя. Так что, как только я прознал о том, что Microsoft разрабатывает свою реализацию языка Ruby — под названием IronRuby — поверх инфраструктуры Microsoft .NET Framework, я почувствовал сильное волнение и с головой окунулся в него.
Благодаря IronRuby миры .NET и Ruby теперь соединены. Это открывает бескрайние возможности, и преимущества такого соединения прямо-таки феноменальны.
В этой статье я намерен рассказать об одном из преимуществ, важных для разработчиков как для .NET Framework, так и Ruby: вы можете использовать IronRuby в Windows Phone 7.
Что такое IronRuby?
О разработке IronRuby Microsoft объявила в 2006 г. На разработку ушло более трех лет, и в апреле группа IronRuby сообщила о первой стабильной версии IronRuby: версия 1.0.
IronRuby поддерживает весь набор функциональности языка Ruby с уникальным добавлением: интеграцией кода Ruby с кодом .NET Framework. Эта интеграция реализована практически бесшовно и требует немногим больше простой загрузки сборки .NET Framework в контекст Ruby. Например, следующий код на IronRuby загружает сборку System.Windows.Forms и использует преимущества ее классов:
require 'System.Windows.Forms'
include System::Windows::Forms
form = Form.new
form.height = 200
form.width = 400
form.text = "IronRuby Window"
form.show_dialog
Эта интеграция возможна благодаря Dynamic Language Runtime (DLR) — уровню, который добавлен в инфраструктуру .NET Framework и предоставляет общие сервисы динамическим языкам, написанным на основе этой инфраструктуры. DLR размещается поверх CLR и значительно упрощает реализацию динамических языков в .NET. Это одна из основных причин появления множества динамических языков в .NET Framework, которое мы наблюдаем в последнее время.Вспомним хотя бы IronRuby, IronPython, IronJS, Nua, ClojureCLR и др.
Ключевые средства IronRuby
Ruby — динамический язык, и IronRuby является таким же. Это означает отсутствие компилятора под рукой, и большинство операций в статических языках, выполнявшихся при компиляции и сборке, осуществляется в период выполнения. Это открывает самые разнообразные возможности, которые трудно или вообще нельзя реализовать в большинстве современных статических языков.
Взаимодействие с объектами .NET Framework Язык Ruby имеет множество реализаций: MRI (изначальная реализация), JRuby, Rubinius, MacRub, IronRuby и др. Что выделяет IronRuby из толпы, так это его способность без проблем взаимодействовать с объектами .NET Framework. Это взаимодействие является двухсторонним:объекты .NET Framework доступны из кода на IronRuby, а объекты IronRuby — из кода .NET Framework.
Динамическая типизация Типы переменных IronRuby определяются в период выполнения, пожэтому указывать их в коде нет нужды. Однако это не означает, что в IronRuby нет типов. Они есть, и каждый тип подчиняется своим правилам, как и типы в статических языках. Следующий код демонстрирует механизм динамической типизации:
# Declaring a numeric variable
a = 1
# The variable is of a numeric type
# and therefore numeric operations are available
a = a * 2 + 8 / 4
# The next line will raise an exception
# because it is not possible to add a string to a number
a = a + "hello"
# However, the next line is entirely legit and will result
# in changing the variable type to String
a = "Hello"
Интерактивная консоль По аналогии с командной строкой Windows интерактивная консоль является приложением, которое принимает код на IronRuby и немедленно исполняет его. Этот поток выполнения также известен под названием Read-Evaluate-Print-Loop (REPL). Вы можете определять переменные, методы и даже классы, загружать файлы IronRuby или сборки .NET Framework и мгновенно использовать их. Например, на рис. 1 показан простой сеанс работы в консоли, в котором класс создается и тут же используется.
Рисунок 1 Применение консоли IronRuby
Типизация по признакам (duck typing) IronRuby — объектно-ориентированный язык. Он поддерживает классы, наследование, инкапсуляцию и управление доступом, как и следовало бы ожидать от объектно-ориентированного языка. Однако он не поддерживает интерфейсы или абстрактные классы в отличие от многих статических языков.
Это не пробел в архитектуре языка. При динамической типизации объявление контрактов кода, таких как интерфейсы или абстрактные классы, становится лишним. Единственное, что имеет значение в объекте, — определяет он конкретный метод или нет, поэтому, если такой метод определен, нет нужды как-то помечать его. Это называют типизацией по признакам (duck typing) (в буквальном переводе:типизацией утки; если нечто крякает как утка и плавает как утка, то это утка, и незачем писать на ней, что это утка).
В примере кода на рис. 2 содержатся два класса с методом say_hi и другим универсальным методом introduce, который получает объект и выполняет его метод say_hi. (Обратите внимание на отсутствие интерфейсов или других механизмов атрибутики.)
Рис. 2 Пример типизации по признакам
class Human
def say_hi
puts "Hi!"
end
end
class Duck
def say_hi
puts "Quack!"
end
end
def introduce(obj)
obj.say_hi
end
human = Human.new
duck = Duck.new
introduce(human) # prints "Hi!"
introduce(duck) # prints "Quack!"
Метапрограммирование IronRuby обладает мощными средствами метапрограммирования. Метапрограммирование — это способ добавления, изменения и даже удаления методов в период выполнения. Например, вы можете добавить методы в класс, написать методы, которые определяют другие методы, или удалить определения методов из существующего класса. На рис. 3 к классу добавляется метод, что отражается на всех текущих и будущих экземплярах этого класса.
Рисунок 3 Добавление метода к классу после его объявления
# Creating a class with no methods
class Demo
end
# Creating an instance of class Demo
d = Demo.new
# Opening the class and adding a new method - hello_world
class Demo
def hello_world
puts "hello world"
end
end
# Using the newly added method on the class instance
d.hello_world # prints "hello world"
Более того, есть специальные методы, которые можно использовать для захвата вызовов к неопределенным методам или константам. С помощью этих методов легко поддерживать динамические имена методов вроде find_by_[имя_поля], где [имя_поля] можно заменить любым значением, например find_by_name, find_by_city или find_by_zipcode.
RubyGems Язык Ruby, каким бы мощным он ни был, никогда не завоевал бы такой популярности без внешних библиотек, которые можно установить и использовать совместно с этим языком.
Основной способ установки библиотек Ruby — через систему RubyGems. Это диспетчер пакетов, который помогает распространять и устанавливать библиотеки Ruby, называемые «драгоценными камнями» (gems). Вам доступны тысячи бесплатных «драгоценных камней», которые охватывают практически все аспекты и задачи программирования, в том числе инфраструктуру тестирования, расчета налогов, веб-разработки и многое другое.
Вы должны понимать, что некоторые библиотеки Ruby зависимы от библиотек C. Эти библиотеки нельзя использовать в текущей версии IronRuby, если только вы не портируете библиотеки C на чистый Ruby или C#.
Сообщество Одна из самых сильных сторон IronRuby — доступ к сообществу разработчиков на Ruby. Перед вами открывается ценный контент в десятках форумов, почтовых рассылках, чатах и блогах, где люди готовы помочь по любому вопросу. Используйте эти ресурсы без колебаний — они крайне полезны.
IronRuby и Silverlight
В Silverlight 2 была введена важная новинка: поддержка DLR-языков. В итоге разработчики могут использовать IronRuby с приложениями Silverlight — от включения этого языка в приложение до полного написания на нем приложений Silverlight.
Но постойте-ка, Silverlight же работает в Windows Phone 7, да? Точно.
Windows Phone 7
Как ожидают некоторые аналитики, следующая мобильная платформа Microsoft, Windows Phone 7, станет фактором, который изменит расстановку игроков в индустрии смартфонов. Помимо стандартных мультисенсорных возможностей и сверкающего нового UI, лучшая новость о Windows Phone 7 с точки зрения разработчика заключается в том, что ее платформой разработки является Silverlight.
Это умный ход со стороны Microsoft — задействовать хорошо зарекомендовавшую себя технологию и тем самым позволить большому количеству разработчиков создавать мобильные приложения практически без дополнительного обучения.
Так как DLR-языки способны работать в среде Silverlight, вы можете использовать преимущества IronRuby и писать с его помощью приложения Windows Phone 7.
Однако вы должны знать о некоторых ограничениях. Windows Phone 7 поставляет с .NET Compact Framework, которая является подмножеством .NET Framework. Compact Framework предназначена для мобильных и встраиваемых приложений и содержит примерно 30% полноценной .NET Framework. Соответственно отсутствует большое количество классов, что, конечно, скажется на том, как работает IronRuby.
Самая большая утрата, влияющая на IronRuby, — пространство имен Reflection. IronRuby использует его для компиляции кода «на лету», чтобы приложения работали быстрее. Однако это лишь оптимизация, а не компонент, обязательный для выполнения простых сценариев и приложений.
Другое ограничение касается того, как создаются новые приложения Windows Phone 7. Их можно создавать только в Visual Studio и только на C#. Это требование вынуждает разработчиков писать код на C#, который вызывает код на IronRuby.
И последнее важное ограничение:библиотеки Ruby не будут работать в Windows Phone 7. Следовательно, чтобы использовать «драгоценный камень», вы должны включить его файлы кода в файлы приложения и применять их, как и любые другие файлы кода IronRuby.
Создание простого приложения на IronRuby в Windows Phone 7
Чтобы приступить к разработке приложения Windows Phone 7, управляемого IronRuby, нужно сначала установить Windows Phone 7 Developer Tools, которые можно скачать с developer.windowsphone.com.
После установки инструментария откройте Visual Studio и выберите File | New | Project. В диалоге New Project укажите категорию Silverlight for Windows Phone и выберите шаблон проекта Windows Phone Application. Присвойте ему имя.
Открыв новый проект, вы заметите простой XAML-файл, созданный за вас. Обратите внимание, что XAML требуется, как правило, для Silverlight и не зависит от конкретного языка. Следовательно, хотя код приложения будет писаться на IronRuby, для создания UI вы должны использовать XAML. В этом простом приложении достаточно XAML-файла по умолчанию, никаких изменений вносить в него в данном случае не надо.
Интересная часть этого приложения — его код. Но, прежде чем мы займемся им, нужно добавить ссылки на сборки IronRuby и DLR. Эти сборки не совсем обычные — нам понадобятся сборки, готовые к применению в Windows Phone 7, и их можно получить по ссылке ironruby.codeplex.com/releases/view/43540#DownloadId=133276. Необходимые сборки вы найдете в папке silverlight/bin скачанного пакета.
Далее нам потребуется написать код на IronRuby. Добавьте к приложению новый текстовый файл и назовите его MainPage.rb. Кроме того, чтобы облегчить установку этого кода на телефон, откройте свойства этого файла и измените значение свойства Build Action на Embedded Resource.
Теперь вставьте в этот файл код с рис. 4.
Рисунок 4 Файл кода на IronRuby, который будет выполняться в Windows Phone 7
# Include namespaces for ease of use
include System::Windows::Media
include System::Windows::Controls
# Set the titles
Phone.find_name("ApplicationTitle").text = "MSDN Magazine"
Phone.find_name("PageTitle").text = "IronRuby& WP7"
# Create a new text block
textBlock = TextBlock.new
textBlock.text = "IronRuby is running on Windows Phone 7!"
textBlock.foreground = SolidColorBrush.new(Colors.Green)
textBlock.font_size = 48
textBlock.text_wrapping = System::Windows::TextWrapping.Wrap
# Add the text block to the page
Phone.find_name("ContentGrid").children.add(textBlock)
Код на IronRuby (рис. 4) весьма прямолинеен: мы задаем заголовки, создаем текстовый блок с неким текстом и добавляем его в страницу. Заметьте, что вы можете использовать все языковые средства Ruby (здесь не показаны), такие как классы, метапрограммирование и библиотеки, с учетом ранее упомянутых ограничений в среде Windows Phone.
Теперь осталось лишь реально запустить код на IronRuby. Чтобы делать это при загрузке приложения, в конструктор класса MainPage надо добавить код с рис. 5 (этот класс находится в файле MainPage.xaml.cs).
Рисунок 5 Добавление кода для запуска IronRuby-кода из конструктора класса
// Allow both portrait and landscape orientations
SupportedOrientations = SupportedPageOrientation.PortraitOrLandscape;
// Create an IronRuby engine and prevent compilation
ScriptEngine engine = Ruby.CreateEngine();
// Load the System.Windows.Media assembly to the IronRuby context
engine.Runtime.LoadAssembly(typeof(Color).Assembly);
// Add a global constant named Phone, which will allow access to this class
engine.Runtime.Globals.SetVariable("Phone", this);
// Read the IronRuby code
Assembly execAssembly = Assembly.GetExecutingAssembly();
Stream codeFile =
execAssembly.GetManifestResourceStream("SampleWPApp.MainPage.rb");
string code = new StreamReader(codeFile).ReadToEnd();
// Execute the IronRuby code
engine.Execute(code);
Код на рис. 5 довольно короткий и наглядно демонстрирует, насколько легко запускать IronRuby-код из кода на C#.
Кроме того, не забудьте добавить в класс следующие выражения using:
using System.Reflection;
using System.IO;
using Microsoft.Scripting.Hosting;
using IronRuby;
В третьей строке кода на рис. 5 загружается сборка System. Windows.Media в контекст IronRuby, что позволяет коду взаимодействовать с классами и перечислениями в этой сборке.
Следующая строка обеспечивает доступ IronRuby-кода к текущей странице Silverlight. В этой строке IronRuby-коду через константу Phone предоставляется текущий экземпляр (this).
В остальном коде из встраиваемого файла считывается IronRuby-код (заметьте, что к имени этого файла должно быть добавлено пространство имен приложения, поэтому MainPage.rb становится SampleWPApp.MainPage.rb), а затем исполняется с помощью экземпляра движка IronRuby.
И это все. Мы создали приложение, которое после загрузки выполняет IronRuby, а тот в свою очередь изменяет заголовки и добавляет текстовый блок в страницу Silverlight. Остается лишь запустить это приложение. Результат запуска показан на рис. 6.
Рисунок 6 Приложение, управляемое IronRuby, выполняется в Windows Phone 7
Постоянное совершенствование
Хотя рабочий процесс не совершенен при использовании IronRuby в Windows Phone 7 и вам нужно постоянно помнить о различных ограничениях, это только начало. Платформы IronRuby и Windows Phone 7 еще молоды, и они будут постоянно развиваться и совершенствоваться.
Комбинация этих платформ открывает много возможностей как разработчикам для .NET Framework, так и разработчикам на Ruby. Теперь .NET-разработчики могут использовать преимущества невероятной мощи языка Ruby при написании приложений Windows Phone 7, например включать в свои приложения консоль IronRuby или предоставлять средства расширения. А с другой стороны, разработчики на Ruby могут — впервые!— писать мобильные приложения на своем языке.