Ruby|Python в браузере, сделай сам

Зачем?

sidebar_gestaltКлиентскую часть в веб-приложениях принято создавать на JavaScript. Я считаю, что большинство разработчиков с огромным удовольствием бы отошли от этого правила и воспользовались своим любимым server-side языком. Ну что же, команда MIX Online предоставила любителям динамических языков такую возможность, подробнее об этом можно прочитать в “Проект Gestalt – пишите на Ruby, Python и XAML прямо в HTML на стороне клиента”. Ниже я предлагаю создать нечто подобное, но уже своими силами.

С помощью чего?

Посмотрев несколько примеров мне стало ясно, что реализован Gestalt на Silverlight + Dynamic Languages Runtime. Далее я прикинул, а на сколько сложно создать нечто своими руками? И сразу же решение: Silverlight умеет  взаимодействовать с DOM – значит я смогу получить код и интерпритировать его – дело за малым – реализация.

Приступим

Нам понадобятся:

  • Visual Studio >2008SP1 (при желании можно и другие IDE или средства редактирования текста)
  • Silverlight >2.0 Tools
  • Dynamic Languages SDK >0.5.0 (download)
  • 10 мин времени

Lets code

image

Открываем Visual Studio, создаём Silverlight Application, я назову проект “mygestalt”. Теперь я осознаю, что писать та надо будет совсем не много, мне понадобится экспериментальный Client-Script и его интерпритатор. Открываем страничку, на которой будет хоститься наш Silverlight, в моём случаем это mygestaltTestPage.aspx и добавляем туда наш client-side python code. Выглядеть это должно примерно так:

  1. <script type="python">
  2. def func():
  3.     HtmlPage.Window.Alert("Hello world!")
  4.    
  5. func()
  6. </script>

* This source code was highlighted with Source Code Highlighter.

Далее отправляемся в MainPage.xaml.cs, где будем заниматься поисками нашего скрипта:

  1. using System.Linq;
  2. using System.Windows.Browser;
  3.  
  4. namespace mygestalt
  5. {
  6.   public partial class MainPage
  7.   {
  8.     public MainPage()
  9.     {
  10.       InitializeComponent();
  11.       FindAndRunScript();
  12.     }
  13.  
  14.     private void FindAndRunScript()
  15.     {
  16.       var scripts = HtmlPage.Document.GetElementsByTagName("script");
  17.       var pythonScript = scripts.Where(x => x.GetProperty("type").ToString() == "python").First();
  18.       PythonEngine.Run(pythonScript.GetProperty("innerHtml").ToString());
  19.     }
  20.   }
  21. }

* This source code was highlighted with Source Code Highlighter.

Ну и реализация PythonEngine:

  1. using Microsoft.Scripting;
  2. using Microsoft.Scripting.Hosting;
  3. using Microsoft.Scripting.Silverlight;
  4.  
  5. namespace mygestalt
  6. {
  7.   public static class PythonEngine
  8.   {
  9.     public static ScriptScope Run(string source)
  10.     {
  11.       var setup = Configuration.LoadFromAssemblies(Package.GetManifestAssemblies());
  12.       setup.HostType = typeof(BrowserScriptHost);
  13.       setup.DebugMode = true;
  14.       var runtime = new ScriptRuntime(setup);
  15.       var engine = runtime.GetEngine("IronPython");
  16.       var scope = engine.CreateScope();
  17.       const string init = @"
  18. import clr
  19. clr.AddReference('System.Windows.Browser')
  20.  
  21. from System.Windows.Browser import *
  22.  
  23. "
  24. ;

  25.  
  26.       ScriptSource initSource = engine.CreateScriptSourceFromString(init, SourceCodeKind.Statements);
  27.       initSource.Execute(scope);
  28.       var script = engine.CreateScriptSourceFromString(source, SourceCodeKind.Statements);
  29.       script.Execute(scope);
  30.  
  31.       return scope;
  32.     }
  33.   }
  34. }

* This source code was highlighted with Source Code Highlighter.

Запускаем приложение и видим:

image

 

 

 

 

В заключение

Вот у нас и получился свой собственный Gestalt, самое интересное в том, что я посмотрел его исходники и нашёл там примерно такую же реализацию.

Мой проект можно найти на http://code.google.com/p/mygestalt/.

Всем спасибо!


Фреймворки для построения композитных приложений на WPF\SL

image[10]

При создании композитных приложений на WPF\SL частенько приходится реализовывать паттерн Model-View-ViewModel, в его имплементации может помочь несколько довольно таки неплохих фреймворков:

  • Caliburn (поддерживает паттерны: MVC, MVP, Presentation Model (MVVM), Commands и Application Controller; TDD, IoC-контейнер дружелюбен)
  • nRoute (так же достаточно мощный фреймворк)
  • Onyx (чуть проще, таргет на MVVM паттерн)
  • Prism/Composite WPF (сильный фреймворк от patterns and practices)

ViewModel Tool

image

Для тех, кто постоянно реализует во ViewModel интерфейс INotifyPropertyChanged. Clarius Consulting Labs выпустила утилиту ViewModel Tool, которая сгенерирует имплементацию интерфейса самостоятельно.


XAML Power Toys

XAML Power Toys – аддин для Visual Studio 2008 SP1 для разработчиков под Silverlight, WPF, облегчающий разработку генерацией XAML’а представений (View), а так же модели представления (ViewModel), со всем необходимыми бизнес-действиями и контролами.

imageПодробнее узнать можно здесь:

http://karlshifflett.wordpress.com/xaml-power-toys/


Практикум Silverlight: Начинаем работать с Composite Application Library

Для кого эта статья

Данный пост будет интересен для вас если:

  1. Вы нацелены на развитие
  2. Вы работаете с RIA средой, такой как Silverlight (так же WPF)
  3. Если вы уже где-то слышали такие слова как Composite Application Guidance, Composite Application Library
  4. Вы заинтересовались статьей Павла ИвченковаСоздание приложения на WPF с использованием принципов TDD 
  5. Вам было интересно прочитать статью AcervUse Case Driven Development и Composite UI Application Block

Цель статьи

В этой статье вы узнаете основы того, что содержится в Composite Application Guidance, а так же научитесь создавать составные Silverlight приложения на основе Composite Application Library (создадите загружаемый модуль (Module), а так же представление (View), которое отобразите в конcоли (Shell))

Приготовимся

В данной статье нам понадобятся следующие сборки из комплекта Composite Application Library и Unity Application Block:

  • Microsoft.Practices.Composite.dll
  • Microsoft.Practices.Composite.Presentation.dll
  • Microsoft.Practices.Composite.UnityExtensions.dll
  • Microsoft.Practices.ServiceLocation.dll
  • Microsoft.Practices.Unity.dll

Composite Application Library распространяется в виде исходных кодов, в связи с этим необходимо скомпилировать следующие сборки:

  • Microsoft.Practices.Composite.dll
  • Microsoft.Practices.Composite.Presentation.dll
  • Microsoft.Practices.Composite.UnityExtensions.dll

Для этого следует запустить исполняемый файл из комплекта

Desktop & Silverlight — Open Composite Application Library.bat

и сбилдить проект в Visual Studio, далее необходимые сборки можно найти в следующей каталоге

CAL\Silverlight\Composite.UnityExtensions\bin\Debug

Приступим

1. Создаём проект с приложением Shell

Для начала создадим Silverlight Application приложение, назовём его HelloWorld.Silverlight, так же не забудем добавить ASP.NET Web приложение для его хостинга. В результате должно получиться примерно следующее:

Dd458947.1153f195-a8e1-43e4-a307-877d6823e346(en-us,MSDN.10).png

Далее добавляем ссылки на необходимые нам сборки:

  • Microsoft.Practices.Composite.dll
  • Microsoft.Practices.Composite.Presentation.dll
  • Microsoft.Practices.Composite.UnityExtensions.dll
  • Microsoft.Practices.Unity.dll
  • Microsoft.Practices.ServiceLocation.dll

Далее нам необходимо создать консоль (Shell) нашего приложения, для этого переименуем Page.xaml в Shell.xaml, а так же изменим название класса в Shell.xaml.cs c Page на Shell.

Так же нам потребуется изменить файл Shell.xaml:

  1. <UserControl x:Class="HelloWorld.Silverlight.Shell"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.     Width="400" Height="300">
  5.     <Grid x:Name="LayoutRoot" Background="White">
  6.  
  7.     </Grid>
  8. </UserControl>

* This source code was highlighted with Source Code Highlighter.

Далее нам необходимо узнать, что такое регион (region) и как мы его будем использовать.

Регион (Region) – концептуальный механизм, используемый разработчиками для отображения представлений (view) в определенном месте контрола, а так же для динамической подмены представлений (view).

В качестве хостинга для региона (region) могут использоваться следующие контролы:

  • System.Windows.Controls.ContentControl
  • System.Windows.Controls.ItemsControl
  • System.Windows.Controls.Primitives.Selector
  • System.Windows.Controls.TabControl

Подробнее о регионах (region) можно прочитать по ссылке http://msdn.microsoft.com/en-us/library/dd458944(printer).aspx

Для того, чтобы добавить регион в нашу консоль, мы будем использовать ItemsControl. В Shell.xaml добавим ссылку на пространство имён

  1. xmlns:Regions="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"

* This source code was highlighted with Source Code Highlighter.

а так же добавим контрол ItemsControl

  1. <UserControl x:Class="HelloWorld.Silverlight.Shell"
  2.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.              xmlns:Regions="clr-namespace:Microsoft.Practices.Composite.Presentation.Regions;assembly=Microsoft.Practices.Composite.Presentation"
  5.              Width="400" Height="300">
  6.     <ItemsControl Name="MainRegion"/>
  7. </UserControl>

* This source code was highlighted with Source Code Highlighter.

так же добавим ему атрибут, указывающий RegionManager на текущий регион по имени “MainRegion”

  1. <ItemsControl Name="MainRegion" Regions:RegionManager.RegionName="MainRegion"/>

* This source code was highlighted with Source Code Highlighter.

Bootstrapper

Bootstrapper – механизм для компоновки компонентов нашего приложения.

Мы создадим свой класс bootstrapper на основе присутствующего в Composite Application Library абстрактного класса UnityBootstrapper, который инициализирует компоненты с помощью контейнера Unity, для этого добавим файл Bootstrapper.cs к нашему проекту и определим наследование:

  1. class Bootstrapper : UnityBootstrapper
  2. {
  3. }

* This source code was highlighted with Source Code Highlighter.

Так же переопределим метод создания консоли CreateShell:

  1. protected override DependencyObject CreateShell()
  2. {
  3.     Shell shell = Container.Resolve<Shell>();
  4.     Application.Current.RootVisual = shell;
  5.     return shell;
  6. }

* This source code was highlighted with Source Code Highlighter.

и определение каталога модулей:

  1. protected override IModuleCatalog GetModuleCatalog()
  2. {
  3.     ModuleCatalog catalog = new ModuleCatalog();
  4.     return catalog;
  5. }

* This source code was highlighted with Source Code Highlighter.

Так же необходимо провести инициализацию bootstrapper’а:

  1. private void Application_Startup(object sender, StartupEventArgs e)
  2. {
  3.     Bootstrapper bootstrapper= new Bootstrapper();
  4.     bootstrapper.Run();
  5. }

* This source code was highlighted with Source Code Highlighter.

Можно запустить проект и проверить.

2. Добавляем модуль (Module)

Module – функциональная, слабо связанная единица, предназначенная для комбинации в приложении.

Для этого нам необходимо добавить проект типа Silverlight Class Library и назвать его HelloWorldModule:

image

Добавляем ссылки на сборки:

  • Microsoft.Practices.Composite.dll
  • Microsoft.Practices.Composite.Presentation.dll

Переименовывем класс Class1 в HelloWorldModule и наследуем его от интерфейса Microsoft.Practices.Composite.Modularity.IModule:

  1. public class HelloWorldModule : IModule
  2. {
  3.  public void Initialize() {}
  4. }

* This source code was highlighted with Source Code Highlighter.

Далее на необходимо зарегистрировать модуль в каталоге нашего Bootstrapper класса, немного изменив метод GetModuleCatalog:

  1. protected override IModuleCatalog GetModuleCatalog()
  2. {
  3.   ModuleCatalog catalog = new ModuleCatalog()
  4.       .AddModule(typeof(HelloWorldModule.HelloWorldModule));
  5.   return catalog;
  6. }

* This source code was highlighted with Source Code Highlighter.

3. Добавляем представление (View)

Создадим в проекте нашего HelloWorldModule модуля папочку Views  и добавим к нему Silverlight User Control под названием HelloWorldView, который будет нашим представлением. Немного подправим HelloWorldView.xaml:

  1. <UserControl x:Class="HelloWorldModule.Views.HelloWorldView"
  2.   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;>
  4.   <Grid x:Name="LayoutRoot" Background="White">
  5. <TextBlock Text="Hello World" Foreground="Green" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Calibri" FontSize="24" FontWeight="Bold"></TextBlock>
  6.   </Grid>
  7. </UserControl>

* This source code was highlighted with Source Code Highlighter.

Region Manager – сервис для несвязанного сопоставления (только с помощью указания имён) представления и региона.

Добавим его в конструктор класса нашего модуля HelloWorldModule через dependency injection и сохраним в поле regionManager:

  1. public HelloWorldModule(IRegionManager regionManager)
  2. {
  3.  this.regionManager = regionManager;
  4. }

* This source code was highlighted with Source Code Highlighter.

Так же зарегистрируем представление в регионе:

  1. public void Initialize()
  2. {
  3.   regionManager.RegisterViewWithRegion("MainRegion", typeof(Views.HelloWorldView));
  4. }

* This source code was highlighted with Source Code Highlighter.

Ну вот вроде и всё. Теперь можно запустить наше приложение:

image

В заключение

Итак, в этой статье вы узнали основы того, что содержится в Composite Application Guidance, а так же научитесь создавать составные Silverlight приложения на основе Composite Application Library (создадили загружаемый модуль (Module), а так же представление (View), которое отображается в конcоли (Shell)). Всё как и было обещано.

Источники

  1. Перед вами был слегка вольный и неполный перевод статьи из Patterns&Practices “Composite Application Guidance for WPF and Silverlight — February 2009”
    Silverlight Hands-On Lab: Getting Started with the Composite Application Library найти её можно по адресу http://msdn.microsoft.com/en-us/library/dd458947(printer).aspx
  2. Скачать руководство и сорцы можно с http://www.codeplex.com/CompositeWPF/

Boo 0.9 уже здесь!

Введение

 

Вчера Bamboo в своем блоге сообщил о релизе Boo 0.9. Стоит обратить внимание на то, что данный релиз заметно преображает язык, делая его более удобным.

Ключевые обновления

 

Основными “фишками” новой версии являются:

  • Генератор макросов [BOO-1077], который больше не ограничивает макросы возвращением единственного значения, либо блока, а позволяет возвращать неограниченное количество веток с помощью yield:
    macro printLines:
        for arg in printLines.Arguments:
            yield [| System.Console.WriteLine($arg) |]
        
    printLines "silly", "silly", "silly"
  • Nestable-макросы [BOO-1120] – описания макросов теперь могут быть вложенными, и поддерживают зависимости от контекста:
    macro given:
        macro when:
            yield [| print "given.when" |]
        yield 

    macro alert:
        macro when:
            yield [| print "alert.when" |]
        yield 
   
    given:
        when // given.when
    
    alert:
        when // alert.when
  • Макросы – как члены типа [BOO-415] – макрос может быть использован в описании тела типа:
    macro ThreadStatic:
        case [| ThreadStatic $name as $type |]:
            yield [|
                [System.ThreadStatic] static $name as $type
            |]
    
    class Environments:
        private ThreadStatic _current as Environment
  • Шаблон соответствия [BOO-1106] – простой, но мощный шаблон соответствия объекта с макросами match/case/otherwise:
   import Boo.Lang.PatternMatching
    
    def Eval(e as Expression) as int:
        match e:
            case Const(Value):
                return Value

            case InfixExpression(Operator: "+", Left, Right):
                return Eval(Left) + Eval(Right)
                
            case InfixExpression(Operator: "-", Left, Right):
                return Eval(Left) - Eval(Right)
  • Поддержка универсальный расширений методов (generic extension methods знакомых нам по C#) [BOO-937] – подобные LINQ расширения:
    import System.Linq.Enumerable from System.Core
    
    [Extension]
    def MakeString[of T](source as T*):
        return join(source, ", ")
    
    evenDoubles = range(10).Where({ i as int | i % 2 == 0 }).Select({ i as int | i * 2 })
    print evenDoubles.MakeString()
  • Общий параметр ограничений [BOO-935] и общий параметр вывода типа [BOO-1102]:
def Using[of T(System.IDisposable)](value as T, block as System.Action[of T]):
        try:
            block(value)
        ensure:
            value.Dispose()
    
    Using(System.IO.File.OpenText("TFM.TXT"), { reader | print reader.ReadLine() })
  • Строгий режим [BOO-1115] – строгий режим меняет некоторые правила компилятора: по-умолчанию все типы становятся private, параметры метода и возвращаемые значения должны быть обязательно объявлены
  • Ассиметричные свойства видимости доступа [BOO-1094]
    class Song:
        Name as string:
            public get:
                return _name
            internal set:
                _name = value
        ...
    def ToHex(n as int):
        return "0x${n:x4}"
    
    print ToHex(42)
  • Поддержка SilverLight [BOO-1117] – пример Владимира Лазунина с его Тетрисом, рабочий проект которого нуждается только в Boo.Lang.dll весит ~46 KB, а аналог, исполненный на IronPython подцепляет библиотеки DLR и весит в целом ~1.15 MB.

Материалы

 

Статья подготовленная по

http://blogs.codehaus.org/people/bamboo/archives/boo.html


Лоуренс Морони "Введение в Silverlight2"

image Ребята из команды Microsoft Россия подготовили нам новогодний подарок, и перевели книжку Лоуренса Морони «Введение в Silverlight2». Скачать её можно здесь.

Думаю стоит прочитать её, освежить свои знания по SL, тем более в следующем году предстоит с ним плотненько поработать.