sticky
Язык Script# - Заметки RRS feed

Все ответы

  • Вводная

    Оглавление | Следующее

    Этой публикацией я начинаю серию заметок по Script#. Этот язык, если можно так его назвать, хотя правильнее его назвать средой C# над JavaScript, показался мне очень интересным и весьма полезным по ряду причин.

    Во-первых, Script# - это прежде всего всем хорошо известный C# моделирующий другой популярный язык JavaScript, и как следствие, мы получаем строгую типизацию и структуру C# над JavaScript.

    Во-вторых, Script# очень хорошо интегрирован в Visual Studio 2010, можно создать проект Script# или какой-то модуль Script#. Проекты на этом языке мало чем отличаются от проектов на C#. Он поддерживается NuGet. Проект компилируется в три файла: библиотеку определений проекта dll, в отладочный и минифицированный файлы JavaScript. Качество компиляции отменное. Для него можно писать такие же модульные тесты, как и для C#. Такая тесная интеграция вряд ли была бы возможна, если бы не тот факт, что этот язык написал ведущий проектировщик ASP.NET от Microsoft Никхил Котари. Надо ли говорить, что в 2008 году он получил приз за этот язык как лучший проект Microsoft, а клиентская часть ASP.NET MVC 3 написана целиком на этом языке.

    В-третьих, этот язык помимо своей среды окружения поддерживает еще и такие популярные библиотека, как MicrosoftAjax и JQuery. Писать код под эти библиотеки стало проще, понятнее и приятнее.

    В-четвертых, приложения написанные на Script# просто великолепны. Просто захватывает дух, когда видишь написанные приложения на Script# (во сяком случае те, которые я видел).

    В-пятых, это отличный бесплатный продукт с открытым кодом.

    Как и во всяком хорошо сделанном проекте, у Script# есть и свои недостатки, но они меркнуть перед его блеском.

    Напоследок несколько ссылок:

    1.                  http://www.nikhilk.net/ - сайт и блог Котари

    2.                  http://projects.nikhilk.net/ScriptSharp - страница проекта. Здесь же можно скачать сам Script#, документацию (немного скудную, но тем не менее вполне сносную), отличные примеры.

    3.                  https://github.com/nikhilk/scriptsharp - исходные коды Script#.


    super_be
    • Изменен тип super_be 7 сентября 2011 г. 16:57 Ошибся с вопросом
    • Объединено ulcerModerator 19 сентября 2011 г. 4:26 Не стоит плодить топики
    • Изменено super_be 24 сентября 2011 г. 11:48
    6 сентября 2011 г. 18:31
  • Отлично!

    Как вы планируете писать заметки - все в этом одном топике или каждая в новом? Много ли их будет, имеет ли смысл делать содержание? Можно прикрепить данную тему, чтобы она всегда была на виду, а вы после можете дополнять ее либо новыми заметками, либо в ней ссылками на заметки, которые будут оформлены отдельными постами на форуме.


    Для связи [mail]
    7 сентября 2011 г. 13:35
  • А как посоветуете? Заметок будет много и их надо как-то будет организовывать. Я тут недавно и поэтому с трудом себе представляю как тут все это лучше организовать.
    super_be
    7 сентября 2011 г. 16:33
  • Установка

    Предыдущее | Оглавление | Следующее

    Заходим на страницу проекта: http://projects.nikhilk.net/ScriptSharp или скачиваем по ссылке http://dl.dropbox.com/u/26621494/Releases/ScriptSharp.0.7.3.0.zip.

    В зависимости от версии ссылка может меняться. Свежую ссылку можно найти на странице проекта.
      Распаковываем архив и запускаем пакет установщика ScriptSharp.msi. Мастер установщика простой, вариантов выбора практически нет, поэтому все время нажимаем кнопку "Next".

    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:29 Объединение мануала в одни топик
    • Изменено super_be 24 сентября 2011 г. 11:54
    7 сентября 2011 г. 17:14
  • Об авторе

    Предыдущее | Оглавление | Следующее

    Никил Котари - ведущий разработчик Microsoft, в конторе занимается вебом и платформой .NET. Закончил Калифорнийский университет, Ирвин. Никил имеет более чем 10-летний опыта разработки Microsoft Web и платформы .NET. Он участвовал в разработке Silverlight, ASP.NET, ASP.NET Ajax, Visual Studio и IIS.

    Как архитектор, Никил полностью отвечает за разработку продуктов и направление веб-платформ и инструментов, которые включают разработку Silverlight и Ajax для интернет приложений, умных клиентских приложений и традиционных Веб-приложений.

    Никил собрал команду разработчиков самого высокого уровня и выпустил несколько версий ASP.NET и .NET. В течение всей своей карьеры в Microsoft Никил зарегистрировал более 50 патентов в области Веб-разработки.

    Никил является одним из самых узнаваемых человек в среде Веб-разработчиков и ведет свой блог в http://www.nikhilk.net. Он является автором книги по разработке ASP.NET. Он участвует в многочисленных конференциях, таких как PDC, TechEd и MIX.

    Помимо своей основной работы в Microsoft он запустил такие новаторские проекты как Script#, Silverlight.FX (http://projects.nikhilk.net) и другие, которые также популярны среди разработчиков, он отбирает новые идеи для будущих проектов Microsoft.

    Его область интересов: разработка программного обеспечения, архитектура программного обеспечения, веб-разработка, веб-платформы, web 2.0, веб-сервисы, платформы пользовательского интерфейса, новаторские проекты, RIA, Ajax, ASP.NET, Silverlight, C#, C++, JavaScript, XML.

    Является лауреатом многочисленных премий Microsoft.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:27 Лучше держать все в одном топике
    • Изменено super_be 24 сентября 2011 г. 11:51
    7 сентября 2011 г. 17:21
  • Установка пакета в NuGet

    Предыдущее | Оглавление | Следующее

    Для работы в ASP.NET MVC можно установить пакет Script# с помощью пакетного менеджера NuGet. Для этого необходимо либо в командной строке NuGet («Вид» -> «Другие окна» -> «Package Manager Console») выполнить команду Install-Package ScriptSharp либо воспользоваться визуальной оболочкой (в «Обозревателе решений» выделить проект, нажать правую кнопку мыши, выбрать каманду «Manage NuGet Packages…», найти средствами поиска пакет «ScriptSharp» и установит его).

    Установка пакета через командную строку

    Установка пакета с помощью визуальной оболочки 

    При установке пакета в проекте в папке «\Content\Scripts» устанавливаются следующие файлы библиотеки:

    ·         mscorlib.debug.js – основная библиотека, обеспечивает расширения стандартных объектов JavaScript и среду программирования скриптов скомпилированных со Script#;

    ·         mscorlib.js – минифицированная версия основной библиотеки;

    ·         ssloader.debug.js – загрузчик скриптов;

    ·         ssloader.js – минифицированная версия загрузчика скриптов.

    Пакет можно также установить и для обычного приложения ASP.NET.

    Веб-страница пакета http://nuget.org/List/Packages/ScriptSharp/0.7.3.0.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:30
    • Изменено super_be 24 сентября 2011 г. 11:59
    7 сентября 2011 г. 17:38
  • Интеграция в Visual Studio 2010

    Предыдущее | Оглавление | Следующее

    Во время установки Script# установщик Windows интегрирует модули и компилятор Script# в Visual Studio 2010. Что же мы имеем в конечном итоге? Какие проекты мы можем создать в Script#? Если добавить новый проект в решение, то в установленных шаблонах появится новый элемент «Script#» содержащий следующие шаблоны:

    1.       jQuery Script Library – проект плагина популярной библиотеки jQuery;

    2.       Script Library – проект простой JavaScript библиотеки;

    3.       Sidebar Gadget – проект гаджета рабочего стола;

    4.       Unit Test – проект тестирования;

    5.       Import Library – проект импорта JavaScript библиотеки.

    Если с первыми четырьмя пунктами все понятно, то последний пункт – по сути, есть проект модульной оболочки над существующей JavaScript библиотекой и предназначен для использования в проектах Script#.

    Какие же элементы мы можем использовать в наших проектах Script#? Добавим в проект Script# новый элемент. Среди установленных увидим:

    1.       Script Class – простой файл Script#;

    2.       jQuery Page Class – класс загрузки плагина jQuery (точка входа в плагин);

    3.       jQuery Plugin Class – класс плагина jQuery;

    4.       Page Class – класс загрузки JavaScript библиотеки (точка входа в библиотеку);

    5.       Scriptlet – класс гаджета рабочего стола;

    6.       Test Class – тестовый класс;

    7.       Resource File – ресурсный файл проекта.

    Проекты Script#

    Элементы проекта Script#


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:31
    • Изменено super_be 24 сентября 2011 г. 12:04
    7 сентября 2011 г. 17:47
  • Постановка задачи

    Предыдущее | Оглавление | Следующее

    Классика жанра – наше первое приложение «Здравствуй мир». Поместим на страницу текстовое поле ввода и кнопку ввода. В текстовом поле ввода попросим ввести имя посетителя. При нажатии мы должны поприветствовать нашего посетителя и сообщить, какое сегодня число. Сам процесс включает в себя отправку имени пользователя на сервер, обработку его и возврат обработанных данных обратно в браузер, где мы и должны отобразить полученную информацию. Вся клиентская часть должна быть написана на JavaScript, а вся серверная часть будет решена на ASP.NET MVC 3. Надо ли говорить, что клиентскую часть напишем на Script#, скомпилированный в JavaScript?

    Исходники:
    http://helloworldscripts.codeplex.com/
    https://github.com/superbe/HelloWorld.Web 


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:31
    • Изменено super_be 28 сентября 2011 г. 18:14
    11 сентября 2011 г. 11:25
  • Создаем веб-приложение

    Предыдущее | Оглавление | Следующее

    Создадим в Visual Studio 2010 веб-приложение ASP.NET MVC 3. Чтобы создать проект выберем пункт меню «Файл» -> «Создать проект…». В диалоговом окне выбираем в «Установленных шаблонах» «Visual C#» «Веб» «Веб-приложение ASP.NET MVC 3». Имя проекта зададим «HelloWorld.Web». Нажимаем кнопку «OK». Во вновь открывшемся диалоговом окне «Создание проекта ASP.NET MVC 3» в списке «Шаблонов проекта» выбираем «Пустой» шаблон. Обработчик представлений выбираем «Razor» и устанавливаем галочку «Использовать разметку семантики HTML5». Нажимаем кнопку «OK». Наш первый проект создан, теперь займемся его наполнением.

    Создаем новое приложение ASP.NET MVC 3
    Создаем новое приложение ASP.NET MVC 3

    Настраиваем содержание нашего веб-приложения
    Настраиваем содержание нашего веб-приложения


    super_be
    • Изменен тип super_be 11 сентября 2011 г. 11:41
    • Объединено ulcerModerator 19 сентября 2011 г. 4:32
    • Изменено super_be 24 сентября 2011 г. 12:23
    11 сентября 2011 г. 11:34
  • Создаем контроллер

    Предыдущее | Оглавление | Следующее

    Создадим контроллер. Для этого в «Обозревателе решений» выделим папку «Controllers» и нажмем правую кнопку мыши. Во всплывающем меню выберем пункт меню «Добавить» -> «Контроллер…». Появится новое диалоговое окно «Добавление контроллера». Назовем наш контроллер «HomeController». «Шаблон» для контроллера выберем «Пустой контроллер». «OK».


    Создаем контроллер

    Наш первый контроллер создан. Ниже приведен текст вновь созданного контроллера.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace HelloWorld.Web.Controllers
    {
        public class HomeController : Controller
        {
            //
            // GET: /Home/
    
            public ActionResult Index()
            {
                return View();
            }
        }
    }
    

    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:32
    • Изменено super_be 24 сентября 2011 г. 12:35
    11 сентября 2011 г. 11:48
  • Создаем представление

    Предыдущее | Оглавление | Следующее

    Создадим представление. В действии «Index» нажмем правую кнопку мыши и во всплывающем меню выберем «Добавить представление…». Настройки оставляем те, которые студия предлагает по умолчанию, но снимаем галочку с «Использовать макет или главную страницу». В нашем приложении будет только одна страница, поэтому усложнять его не будем. Нажимаем «OK».

    Создаем представление
    Создаем представление

    Во вновь созданной странице изменим верстку следующим образом:

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
      <title>Здравствуй мир</title>
      <style type="text/css">
        body { font-family: Georgia; }
        h1 { margin-bottom: 0px; }
        h2 { font-weight: normal; font-style: italic; font-family: Georgia; font-size: 10pt; padding-left: 20px; }
        input, button { font-family: Trebuchet MS; font-size: 16pt; }
      </style>
    </head>
    <body>
      <h1>Здравствуй мир</h1>
      <h2>Да прибудет с Вами сила Script#!</h2>
      <hr />
      <label>Как Ваше имя?</label><br /><br />
      <input type="text" id="nameTextBox" />
      <button type="button" id="helloButton">Привет</button>
      <script src="../../Scripts/mscorlib.js" type="text/javascript"></script>
      <script src="../../Scripts/HelloWorld.Scripts.js" type="text/javascript"></script>
    </body>
    </html>
    

    Здесь мы положили одно текстовое поле ввода и кнопку. В тестовом поле ввода попросим ввести имя посетителя, а кнопкой запустить все механизмы. Ссылки на скрипты внизу страницы можно добавить позже. Первый скрипт – это библиотека Script#, расширяющая основные и добавляющая новые объекты JavaScript. Второй – это наша будущая библиотека.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:33
    • Изменено super_be 24 сентября 2011 г. 12:39
    11 сентября 2011 г. 11:57
  • Действие обрабатывающее наш запрос

    Предыдущее | Оглавление | Следующее

    Пришло время добавить в наш контроллер новое действие. Это действие будет отвечать за обработку запросов посетителя, т.е. оно должно принять имя пользователя, обработать его и вернуть некоторый объект, в нашем случае возвращаем строку приветствия и сегодняшнее число.

    Для начала подготовим наш возвращаемый объект. Для этого создадим модель, содержащую два свойства: строку приветствия и дату. Эта модель реализует бизнес-логику нашего приложения. В папке «Models» создадим новый класс C# и назовем его «Hello». В конструктор созданного класса передадим имя посетителя и, выполнив нехитрые манипуляции с ним, соберем строку приветствия, а так же зададим сегодняшнее число:

    namespace HelloWorld.Web.Models
    {
        using System;
    
        /// <summary>
        /// Наша модель реализует бизнес-логику приложения: 
        /// она формирует строку приветствия и дату.
        /// </summary>
        public class Hello
        {
            /// <summary>
            /// Строка приветствия.
            /// </summary>
            public string Greeting { get; set; }
            
            /// <summary>
            /// Дата обращения.
            /// </summary>
            public string TimeStamp { get; set; }
    
            /// <summary>
            /// Конструктор. Получает имя пользователя и формирует строку приветствия.
            /// </summary>
            /// <param name="name">Имя пользователя.</param>
            public Hello(string name)
            {
                // Формируем строку приветствия.
                Greeting = string.Format("Здравствуйте, {0}! Сегодня ", name);
                
                // Задаем дату обращения пользователя.
                TimeStamp = DateTime.Now.ToString("D");
            }
        }
    }
    

    Модель готова, теперь мы получаем готовый бизнес-объект одной строкой new Hello(name). Преобразуем его в JSON-объект и вернем его клиентской части нашего приложения. В наш контроллер добавим следующий код:

            public JsonResult World(string name)
            {
                return Json(new Hello(name), JsonRequestBehavior.AllowGet);
            }
    

    Здесь указан атрибут JsonRequestBehavior.AllowGet, который разрешает приложению передавать приложению JSON-объект в запросе GET. Таким образом, мы имеем следующий текст котроллера:

    namespace HelloWorld.Web.Controllers
    {
        using System.Web.Mvc;
        using Models;
    
        /// <summary>
        /// Контроллер нашего приложения.
        /// </summary>
        public class HomeController : Controller
        {
            //
            // GET: /Home/
    
            /// <summary>
            /// Отображаем нашу страницу.
            /// </summary>
            /// <returns>Представление нашего приложения.</returns>
            public ActionResult Index()
            {
                return View();
            }
    
            //
            // GET: /Home/World
    
            /// <summary>
            /// Получить имя пользователя, обработать его и вернуть готовый JSON-объект.
            /// </summary>
            /// <param name="name">Имя пользователя.</param>
            /// <returns>Готовый JSON-объект.</returns>
            public JsonResult World(string name)
            {
                return Json(new Hello(name), JsonRequestBehavior.AllowGet);
            }
        }
    }
    

    Обратите внимание, что входной параметр нашего действия поименован как «name», следовательно мы должны изменить маршрут нашего URL-запроса, чтобы наше действие отработало так, как задумано. Для этого откроем «Global.asax» и внесем в него в маршруте следующие изменения:

            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
                routes.MapRoute(
                    "Default", // Имя маршрута
                    "{controller}/{action}/{name}", // URL-адрес с параметрами
                    new { controller = "Home", action = "Index", name = UrlParameter.Optional } // Параметры по умолчанию
                );
    
            }
    

    - заменим везде имя параметра «id» на «name».


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:34
    • Изменено super_be 24 сентября 2011 г. 12:42
    11 сентября 2011 г. 12:09
  • Создаем проект Script#

    Предыдущее | Оглавление | Следующее

    Создадим теперь библиотеку, которая реализует клиентский механизм передачи данных посетителя на сервер, получение обработанных данных и отображение их посетителю. Для этого в «Обозревателе решений» выделим решение и нажмем правую кнопку мыши. Во всплывающем меню выберем пункт меню «Добавить» -> «Создать проект…». Появится диалоговое окно «Добавить новый проект». В диалоговом окне выбираем в «Установленных шаблонах» «Script#» «Script Library». Имя проекта зададим «HelloWorld.Scripts». Нажимаем кнопку «OK».

    Создаем библиотеку Script#
    Создаем библиотеку Script#

    Во вновь открывшемся диалоговом окне «Script# Project Options» в поле ввода «Script Deployment Folder (optional):» задаем путь к папке скриптов в нашем веб-приложении. Наш Script# проект создан. Удалим из проекта созданный по умолчанию класс class1.cs.

    Указываем путь к папке публикации
    Указываем путь к папке публикации


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:34
    • Изменено super_be 24 сентября 2011 г. 12:45
    11 сентября 2011 г. 12:16
  • Класс загрузки «Page Script»

    Предыдущее | Оглавление | Следующее

    Добавим в только что созданный проект класс загрузки JavaScript библиотеки. Для этого в «Обозревателе решений» выделим проект «HelloWorld.Scripts» и нажмем правую кнопку мыши. Во всплывающем меню выберем пункт меню «Добавить» -> «Создать элемент…». В диалоговом окне «Добавление нового элемента – HelloWorld.Scripts» выбираем в «Установленных шаблонах» «Script#» «Page Script». Имя классу дадим «HelloWorldPage». Нажимаем кнопку «OK».

    Создаем загрузчик библиотеки, своего рода точку входа
    Создаем загрузчик библиотеки, своего рода точку входа

    Добавим в класс код, реализующий нашу функциональность:

    // HelloWorldPage.cs
    //
    
    namespace HelloWorld.Scripts
    {
        using System;
        using System.Html;
        using System.Net;
        using System.Runtime.CompilerServices;
    
        /// <summary>
        /// Скрипт загрузки.
        /// </summary>
        [GlobalMethods]
        internal static class HelloWorldPage
        {
            /// <summary>
            /// Конструктор.
            /// </summary>
            static HelloWorldPage()
            {
                // Ищем кнопку «helloButton».
                Element helloButton = Document.GetElementById("helloButton");
                // Задаем обработчик события нажатия этой кнопки.
                helloButton.AddEventListener("click", delegate
                {
                    // Ищем текстовое поле ввода.
                    InputElement nameTextBox = Docu-ment.GetElementById("nameTextBox").As<InputElement>();
                    // Создаем объект XmlHttpRequest.
                    XmlHttpRequest xhr = new XmlHttpRequest();
                    // Открываем этот объект XmlHttpRequest, передав ему часть пути 
                    // URL в который включили имя посетителя.
                    xhr.Open(HttpVerb.Get, "/Home/World/" + nameText-Box.Value.EncodeUriComponent());
                    // Задаем обработку события получения результата.
                    xhr.OnReadyStateChange = delegate
                    {
                        // Проверяем состояние загрузки результата запроса.
                        if (xhr.ReadyState == ReadyState.Loaded)
                        {
                            // Десериализуем полученную JSON-строку в объект JavaScript.
                            ServerResult data = (ServerResult) Script.Eval("(" + xhr.ResponseText + ")");
                            // Формируем строку, отображаемую посетителю.
                            string greeting = String.Format("{0}{1}...", data.Greeting, da-ta.TimeStamp);
                            // Отображаем посетителю приветствие.
                            Script.Alert(greeting);
                        }
                    };
                    // Выполняем запрос.
                    xhr.Send();
                }, false);
            }
        }
    }
    

    Ищем кнопку «helloButton». Задаем обработчик события нажатия этой кнопки. Ищем текстовое поле ввода. Создаем объект XmlHttpRequest. Открываем этот объект XmlHttpRequest, передав ему часть пути URL, в который включили имя посетителя. Задаем обработку события получения результата. Проверяем состояние загрузки результата запроса. Десериализуем полученную JSON-строку в объект JavaScript. Формируем строку, отображаемую посетителю. Отображаем посетителю приветствие. Выполняем запрос.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:35
    • Изменено super_be 24 сентября 2011 г. 12:48
    11 сентября 2011 г. 12:25
  • Класс импорта объекта JSON

    Предыдущее | Оглавление | Следующее

    Обратите внимание, что полученный результат мы передаем в некоторый объект, который не реализован. Он должен моделировать тот JSON-объект, который мы получили из нашей модели. Создадим этот объект. Добавим в проект класс JavaScript библиотеки. Для этого в «Обозревателе решений» выделим проект «HelloWorld.Scripts» и нажмем правую кнопку мыши. Во всплывающем меню выберем пункт меню «Добавить» -> «Создать элемент…». В диалоговом окне «Добавление нового элемента – HelloWorld.Scripts» выбираем в «Установленных шаблонах» «Script#» «Script Class». Имя классу дадим «ServerResult». Нажимаем кнопку «OK».

    Создаем класс возвращаемого результата
    Создаем класс возвращаемого результата

    Доработаем класс:

    // ServerResult.cs
    //
    
    namespace HelloWorld.Scripts
    {
        using System;
        using System.Runtime.CompilerServices;
    
        /// <summary>
        /// Модельный класс.
        /// </summary>
        [Imported]
        [IgnoreNamespace]
        public class ServerResult : Record
        {
            /// <summary>
            /// Строка приветствия.
            /// </summary>
            [PreserveCase]
            public string Greeting;
            
            /// <summary>
            /// Сегодняшнее число.
            /// </summary>
            [PreserveCase]
            public string TimeStamp;
        }
    }
    

    Этот класс наследует классу «Record», который представляет собой удобную обертку для моделирования простых JSON-объектов. В класс передаем следующие атрибуты: «Imported» - атрибут означает, что мы просто моделируем существующие структуры, при этом класс не преобразуется в JavaScript код, но мы можем использовать обращение к нему в наших классах; «IgnoreNamespace» - атрибут дающий команду компилятору игнорировать пространство имен у этого класса. Атрибуты полей указывают на соблюдение определенной нотации при компилировании конечного JavaScript кода. Это необходимо для соответствия полям исходного объекта модели приложения.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:35
    • Изменено super_be 24 сентября 2011 г. 12:52
    11 сентября 2011 г. 12:32
  • Завершение проекта

    Предыдущее | Оглавление | Следующее

    Настало время построить наш проект. В «Обозревателе решений» выделим решение и нажмем правую кнопку мыши. Во всплывающем меню выберем пункт меню «Построить решение». Если до этого мы все сделали правильно, то в папке, которую мы указали при создании проекта Script#, появятся 4 файла: HelloWorld.Scripts.debug.js, HelloWorld.Scripts.js, mscorlib.debug.js и mscorlib.js.

    Состав нашего веб-приложения
    Состав нашего веб-приложения

    Первый файл – это наша JavaScript библиотека, второй – это тоже наша библиотека, только минифицированная, т.е. откомпилирована таким образом, чтобы ее размер был минимальным, для высоконагруженных приложений – это существенный факт, третий – файл расширения JavaScript, последние – его минифицированный вариант. Файлы с текстом «debug», необходимы для отладки библиотеки, файлы без этого текста – это конечные файлы и именно они должны использоваться в конечной сборке. Включим все четыре файла в проект «HelloWorld.Web»и добавим ссылки на них в файле верстки «Index.cshtml». Откроем файл «HelloWorld.Scripts.debug.js». Мы получили правильный и красивый JavaScript.

    //! HelloWorld.Scripts.debug.js
    //
    
    (function() {
    
    Type.registerNamespace('HelloWorld.Scripts');
    
    ////////////////////////////////////////////////////////////////////////////////
    // HelloWorld.Scripts._helloWorldPage
    
    
    
    (function () {
        var helloButton = document.getElementById('helloButton');
        helloButton.addEventListener('click', function() {
            var nameTextBox = document.getElementById('nameTextBox');
            var xhr = new XMLHttpRequest();
            xhr.open('GET', '/Home/World/' + encodeURIComponent(nameTextBox.value));
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    var data = eval('(' + xhr.responseText + ')');
                    var greeting = String.format('{0}{1}...', data.Greeting, data.TimeStamp);
                    alert(greeting);
                }
            };
            xhr.send();
        }, false);
    })();
    })();
    
    //! This script was generated using Script# v0.7.3.0
    

    Откроем папку проекта «HelloWorld.Scripts» в «Проводнике» и перейдем в папку «\bin\Debug». Здесь мы увидим те же четыре файла и еще два новых. Это файл «HelloWorld.Scripts .dll» - это библиотечный файл, который мы можем использовать в наших любых других проектах Script#, использующих нашу JavaScript библиотеку. Этот файл обеспечивает доступ к пространству имен, классам нашей библиотеки. Эта «dll» является простой декларативной библиотекой. Второй файл – стандартный XML-файл, который содержит все скомпилированные комментарии нашей библиотеки.

    Пришло время добавить наши скрипты, если раньше этого не сделали, в файл «Index.cshtml». Для этого надо прописать две строчки:

      <script src="../../Scripts/mscorlib.js" type="text/javascript"></script>
      <script src="../../Scripts/HelloWorld.Scripts.js" type="text/javascript"></script>
    

    - либо просто перетащить эти файлы в конец верстки страницы. Внимание! Последовательность следования важна, сперва располагаем библиотеки окружения, а затем уже наши библиотеки.

    Запустим проект, нажав кнопку «F5» или «Ctrl+F5». На загрузившейся странице в текстовом поле ввода введем имя и нажмем кнопку «Привет». Если все правильно сделано, то загрузится диалоговое окно с нашим приветствием. Поздравляю! Наше первое приложение заработало.

    Конечное веб-приложение
    Конечное веб-приложение


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:36
    • Изменено super_be 24 сентября 2011 г. 12:55
    11 сентября 2011 г. 12:40
  • Очень прошу высказываться, что непонятно, что не так, где ошибка, что дополнить... Заранее благодарен.
    super_be
    11 сентября 2011 г. 20:19
  • Как работает компилятор

    Предыдущее | Оглавление | Следующее

    Рассмотрим, как работает компилятор Script#. При построении проекта запускается компилятор Script#, который анализирует связанные сборки и исходный код и преобразует код C# в код JavaScrip. Затем запускается компилятор C#, который так же анализирует связанные сборки и исходный код и преобразует код C# в библиотеку определений dll. После чего полученные файлы публикуются.



    super_be
    • Изменен тип super_be 12 сентября 2011 г. 16:35
    • Объединено ulcerModerator 19 сентября 2011 г. 4:36
    • Изменено super_be 24 сентября 2011 г. 12:59
    12 сентября 2011 г. 16:32
  • Некоторые приемы

    Предыдущее | Оглавление | Следующее

    Некоторые из общих методов Script#, таких как предупреждения, подсказки, и подтверждения, в действительности являются методами объектов диалоговых окон DHTML, которые затем преобразуются компилятором в их аналоги JavaScript. Некоторые из них вызываются из статического класса Script.

    Script.Alert()

    Оконные сообщения можно смоделировать с помощью метода Alert:

    // C# 
    Script.Alert("Здравствуй мир!");
    

    В итоге получим следующий код JavaScript:

    // JavaScript 
    alert('\u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439 \u043c\u0438\u0440!');
    

    Здесь следует обратить внимание на то, в какой кодировке сохраняется исходный C# файл. Для того, чтобы наше сообщение правильно отобразилось необходимо сохранять исходный файл в кодировке «UTF-8», в противном случае наше сообщение будет представлять просто набор символов.

    JSON десериализация

    В JavaScript есть глобальная функция eval, которая позволяет Вам выполнять код JavaScript или десериализовать JavaScript объекты из их строкового представления. В Script# эта функция моделируется соответствующим методом Script:

    // C# 
    string code = …; 
    object result = Script.Eval(code);
    

    В итоге получим следующий код: 

    // JavaScript 
    var code = …;
    var result = eval(code);
    

    Пример десериализации: 

    // C# 
    object data = Script.Eval("[ { name: \"abc\", value: 123 } ]");
    

    Литералы

    Для очень спорных случаев, если непонятно как смоделировать тот или иной JavaScript код на помощь приходят литералы – специальный метод статического класса Script, который вставляет строку в код JavaScript:

    // C# 
    object someValue = new object();
    Script.Literal("document.body.someExpando = {0}", someValue); 
    object value = Script.Literal("document.body.someExpando");
    

    JavaScript код: 

    // JavaScript 
    var someValue = { };
    document.body.someExpando = someValue;
    var value = document.body.someExpando;
    

    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:37
    • Изменено super_be 24 сентября 2011 г. 13:02
    18 сентября 2011 г. 14:50
  • Объекты

    Предыдущее | Оглавление | Следующее

    В JavaScript всё является объектом, лишь за двумя исключениями — null и undefined. Поэтому строгая типизация в Script# вносит некоторый порядок в эту сумятицу, но, тем не менее, позволяет все это хорошо моделировать:

    // C# 
    false.ToString();
    new int[]{1,2,3}.ToString();
    Action Foo = new Action(delegate(){});
    Type.SetField(Foo, "bar", 1);
    Type.GetField(Foo, "bar");
    2.ToString();
    

    Это все объекты JavaScript: 

    // JavaScript 
    false.toString();
    ([ 1, 2, 3 ]).toString();
    var Foo = function() {
    };
    Foo.bar = 1;
    Foo.bar;
    (2).toString();
    

    Объекты в Scrip# можно моделировать также с помощью простых объектов и словарей:

    // C# 
    object boo = new object();
    Dictionary<string, int> foo = new Dictionary<string, int>();
    Dictionary<string, int> bar = new Dictionary<string, int>("test",12);
    

    Это все объекты JavaScript: 

    // JavaScript 
    var foo = { };
    var bar = { test: 12 };

    super_be
    • Изменен тип super_be 18 сентября 2011 г. 15:57
    • Объединено ulcerModerator 19 сентября 2011 г. 4:38
    • Изменено super_be 24 сентября 2011 г. 13:05
    18 сентября 2011 г. 14:59
  • Поля

    Предыдущее | Оглавление | Следующее

    В JavaScript с помощью механизма позднего связывания получить доступ к полю объекта можно двумя способами: используя либо точечную нотацию, либо запись квадратными скобками. Оба варианта одинаковы по принципу работы — одна лишь разница в том, что использование квадратных скобок позволяет устанавливать свойства динамически. Однако C# не поддерживает позднее связывание. Script# обеспечивает ряд API, которые позволяют Вам явно связать код позднее:

    // C# 
    Dictionary<string, int> foo = new Dictionary<string, int>("name", "Kitten");
    Type.GetField(foo, "name");
    Type.GetField(foo, (string)"name");
    string get = "name";
    Type.GetField(foo, get);
    Type.GetField(foo, "12345");
    

    JavaScript: 

    // JavaScript 
    var foo = { name: 'Kitten' };
    foo.name;
    foo['name'];
    var get = 'name';
    foo[get];
    foo['12345'];
    

    Обращаться к полям объектов в Script# позволяют методы запечатанного класса «Type». Чтобы задать поле объекта необходимо вызвать метод «SetField», который принимает три параметра: собственно сам объект, поле которого задаем, строковое наименование поля и его значение. Доступ к значению поля обеспечивает метод «GetField», который принимает два входных параметра: сам объект и строковое наименование поля.

    // C# 
    Type.SetField(Foo, "bar", 1);
    Type.GetField(Foo, "bar");
    

    JavaScript: 

    // JavaScript 
    Foo.bar = 1;
    Foo.bar;
    

    Удаление поля моделируется методом «DeleteField», в который так же передаются сам объект и строковое наименование поля:

    // C# 
    Dictionary<string, int> obj = new Dictionary<string, int>("bar", 1, "foo", 2, "baz", 3);
    Type.SetField(obj, "bar", Script.Literal("undefined"));
    Type.SetField(obj, "foo", null);
    Type.DeleteField(obj, "baz");
    

    JavaScript: 

    // JavaScript 
    var obj = { bar: 1, foo: 2, baz: 3 };
    obj.bar = undefined;
    obj.foo = null;
    delete obj.baz;
    

    super_be
    • Изменен тип super_be 18 сентября 2011 г. 15:56
    • Объединено ulcerModerator 19 сентября 2011 г. 4:38
    • Изменено super_be 24 сентября 2011 г. 13:11
    18 сентября 2011 г. 15:09
  • Ссылки

    Предыдущее | Оглавление | Следующее

    Script#

    Примеры

    JavaScript


    super_be
    • Изменен тип super_be 18 сентября 2011 г. 15:56
    • Объединено Abolmasov Dmitry 19 сентября 2011 г. 12:04
    • Изменено super_be 3 октября 2011 г. 16:28
    18 сентября 2011 г. 15:25
  • Action()

    Предыдущее | Оглавление | Следующее 

    public delegate void Action()

    Член System 

    Инкапсулирует метод, который не принимает ни одного параметра и не возвращает значений.

    Пример: 

    // C# 
    Action action = new Action(delegate() { Script.Alert("Action"); });
    action.Invoke();
    Action action1 = delegate() { Script.Alert("Action"); };
    
    // JavaScript 
    var action = function() {
        alert('Action');
    };
    action();
    var action1 = function() {
        alert('Action');
    };
    

    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:39
    • Изменено super_be 24 сентября 2011 г. 14:24
    18 сентября 2011 г. 16:11
  • Action(T obj)

    Предыдущее | Оглавление | Следующее 

    public delegate void Action<in T>(T obj)

    Член System 

    Инкапсулирует метод, который принимает один параметр и не возвращает значений.

    Параметры типов:

    T: Тип параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, что можно использовать либо указанный тип, либо менее производный тип.

    Параметры:

    obj: Параметр метода, инкапсулируемого данным делегатом.

    Пример:

    // C# 
    Action<string> getLogin = new Action<string>(delegate(string name) { Script.Alert(name); });
    getLogin.Invoke("super_be");
    
    
    // JavaScript 
    var getLogin = function(name) {
        alert(name);
    };
    getLogin('super_be');
    

    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:39
    • Изменено super_be 24 сентября 2011 г. 14:26
    18 сентября 2011 г. 16:29
  • Action(T1 arg1, T2 arg2)

    Предыдущее | Оглавление | Следующее 

    public delegate void Action<in T1,in T2>(T1 arg1, T2 arg2)

    Член System 

    Инкапсулирует метод, который принимает два параметра и не возвращает значение.

    Параметры типов:

    T1: Тип первого параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, что можно использовать либо указанный тип, либо менее производный тип.

    T2: Тип второго параметра метода, инкапсулируемого данным делегатом.

    Параметры:

    arg1: Первый параметр метода, инкапсулируемого данным делегатом.

    arg2: Второй параметр метода, инкапсулируемого данным делегатом.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:40
    • Изменено super_be 24 сентября 2011 г. 14:27
    18 сентября 2011 г. 16:35
  • Action(T1 arg1, T2 arg2, T3 arg3)

    Предыдущее | Оглавление | Следующее 

    public delegate void Action<in T1,in T2,in T3>(T1 arg1, T2 arg2, T3 arg3)

    Член System 

    Инкапсулирует метод, который принимает три параметра и не возвращает значений.

    Параметры типов:

    T1: Тип первого параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, что можно использовать либо указанный тип, либо менее производный тип.

    T2: Тип второго параметра метода, инкапсулируемого данным делегатом.

    T3: Тип третьего параметра метода, инкапсулируемого данным делегатом.

    Параметры:

    arg1: Первый параметр метода, инкапсулируемого данным делегатом.

    arg2: Второй параметр метода, инкапсулируемого данным делегатом.

    arg3: Третий параметр метода, инкапсулируемого данным делегатом.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:40
    • Изменено super_be 24 сентября 2011 г. 14:32
    18 сентября 2011 г. 16:36
  • Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

    Предыдущее | Оглавление | Следующее 

    public delegate void Action<in T1,in T2,in T3,in T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

    Член System 

    Инкапсулирует метод, который принимает четыре параметра и не возвращает значение.

    Параметры типов:

    T1: Тип первого параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, что можно использовать либо указанный тип, либо менее производный тип.

    T2: Тип второго параметра метода, инкапсулируемого данным делегатом.

    T3: Тип третьего параметра метода, инкапсулируемого данным делегатом.

    T4: Тип четвертого параметра метода, инкапсулируемого данным делегатом.

    Параметры:

    arg1: Первый параметр метода, инкапсулируемого данным делегатом.

    arg2: Второй параметр метода, инкапсулируемого данным делегатом.

    arg3: Третий параметр метода, инкапсулируемого данным делегатом.

    arg4: Четвертый параметр метода, инкапсулируемого данным делегатом.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:47
    • Изменено super_be 24 сентября 2011 г. 14:34
    18 сентября 2011 г. 16:38
  • Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)

    Предыдущее | Оглавление | Следующее 

    public delegate void Action<in T1,in T2,in T3,in T4,in T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)

    Член System 

    Инкапсулирует метод, который принимает пять параметров и не возвращает значений.

    Параметры типов:

    T1: Тип первого параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, что можно использовать либо указанный тип, либо менее производный тип.

    T2: Тип второго параметра метода, инкапсулируемого данным делегатом.

    T3: Тип третьего параметра метода, инкапсулируемого данным делегатом.

    T4: Тип четвертого параметра метода, инкапсулируемого данным делегатом.

    T5: Тип пятого параметра метода, инкапсулируемого данным делегатом.

    Параметры:

    arg1: Первый параметр метода, инкапсулируемого данным делегатом.

    arg2: Второй параметр метода, инкапсулируемого данным делегатом.

    arg3: Третий параметр метода, инкапсулируемого данным делегатом.

    arg4: Четвертый параметр метода, инкапсулируемого данным делегатом.

    arg5: Пятый параметр метода, инкапсулируемого данным делегатом.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:48
    • Изменено super_be 24 сентября 2011 г. 14:36
    18 сентября 2011 г. 16:39
  • Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)

    Предыдущее | Оглавление | Следующее 

    public delegate void Action<in T1,in T2,in T3,in T4,in T5,in T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)

    Член System 

    Инкапсулирует метод, который принимает шесть параметров и не возвращает значений.

    Параметры типов:

    T1: Тип первого параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, что можно использовать либо указанный тип, либо менее производный тип.

    T2: Тип второго параметра метода, инкапсулируемого данным делегатом.

    T3: Тип третьего параметра метода, инкапсулируемого данным делегатом.

    T4: Тип четвертого параметра метода, инкапсулируемого данным делегатом.

    T5: Тип пятого параметра метода, инкапсулируемого данным делегатом.

    T6: Тип шестого параметра метода, инкапсулируемого данным делегатом.

    Параметры:

    arg1: Первый параметр метода, инкапсулируемого данным делегатом.

    arg2: Второй параметр метода, инкапсулируемого данным делегатом.

    arg3: Третий параметр метода, инкапсулируемого данным делегатом.

    arg4: Четвертый параметр метода, инкапсулируемого данным делегатом.

    arg5: Пятый параметр метода, инкапсулируемого данным делегатом.

    arg6: Шестой параметр метода, инкапсулируемого данным делегатом.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:48
    • Изменено super_be 24 сентября 2011 г. 14:40
    18 сентября 2011 г. 16:40
  • Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)

    Предыдущее | Оглавление | Следующее 

    public delegate void Action<in T1,in T2,in T3,in T4,in T5,in T6,in T7>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)

    Член System 

    Инкапсулирует метод, который принимает семь параметров и не возвращает значений.

    Параметры типов:

    T1: Тип первого параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, что можно использовать либо указанный тип, либо менее производный тип.

    T2: Тип второго параметра метода, инкапсулируемого данным делегатом.

    T3: Тип третьего параметра метода, инкапсулируемого данным делегатом.

    T4: Тип четвертого параметра метода, инкапсулируемого данным делегатом.

    T5: Тип пятого параметра метода, инкапсулируемого данным делегатом.

    T6: Тип шестого параметра метода, инкапсулируемого данным делегатом.

    T7: Тип седьмого параметра метода, инкапсулируемого данным делегатом.

    Параметры:

    arg1: Первый параметр метода, инкапсулируемого данным делегатом.

    arg2: Второй параметр метода, инкапсулируемого данным делегатом.

    arg3: Третий параметр метода, инкапсулируемого данным делегатом.

    arg4: Четвертый параметр метода, инкапсулируемого данным делегатом.

    arg5: Пятый параметр метода, инкапсулируемого данным делегатом.

    arg6: Шестой параметр метода, инкапсулируемого данным делегатом.

    arg7: Седьмой параметр метода, инкапсулируемого данным делегатом.


    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:49
    • Изменено super_be 24 сентября 2011 г. 14:41
    18 сентября 2011 г. 16:42
  • Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)

    Предыдущее | Оглавление | Следующее

    public delegate void Action<in T1,in T2,in T3,in T4,in T5,in T6,in T7,in T8>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)

    Член System 

    Инкапсулирует метод, который принимает восемь параметров и не возвращает значений.

    Параметры типов:

    T1: Тип первого параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, что можно использовать либо указанный тип, либо менее производный тип.

    T2: Тип второго параметра метода, инкапсулируемого данным делегатом.

    T3: Тип третьего параметра метода, инкапсулируемого данным делегатом.

    T4: Тип четвертого параметра метода, инкапсулируемого данным делегатом.

    T5: Тип пятого параметра метода, инкапсулируемого данным делегатом.

    T6: Тип шестого параметра метода, инкапсулируемого данным делегатом.

    T7: Тип седьмого параметра метода, инкапсулируемого данным делегатом.

    T8: Тип восьмого параметра метода, инкапсулируемого данным делегатом.

    Параметры:

    arg1: Первый параметр метода, инкапсулируемого данным делегатом.

    arg2: Второй параметр метода, инкапсулируемого данным делегатом.

    arg3: Третий параметр метода, инкапсулируемого данным делегатом.

    arg4: Четвертый параметр метода, инкапсулируемого данным делегатом.

    arg5: Пятый параметр метода, инкапсулируемого данным делегатом.

    arg6: Шестой параметр метода, инкапсулируемого данным делегатом.

    arg7: Седьмой параметр метода, инкапсулируемого данным делегатом.

    arg8: Восьмой параметр метода, инкапсулируемого данным делегатом. 

    Пример: 

    // C# 
    Action<string, string, string, string, string, string, string, int> registration = new Action<string, string, string, string, string, string, string, int>(delegate(string name, string login, string password, string confirmpassword, string confidentialQuestion, string confidentialAnswer, string email, int age) { });
    registration.Invoke("Eugene", "super_be", "*****", "*****", "Как зовут кота?", "Барсик", "***@***.ru", 100);
    
    // JavaScript 
    var registration = function(name, login, password, confirmpassword, confidentialQuestion, confidentialAnswer, email, age) {
    };
    registration('Eugene', 'super_be', '*****', '*****', '\ufffd\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd?', '\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd', '***@***.ru', 100);
    

    super_be
    • Объединено ulcerModerator 19 сентября 2011 г. 4:49
    • Изменено super_be 24 сентября 2011 г. 14:44
    18 сентября 2011 г. 16:44
  • Топики были объеденены в один, чтобы все было в одном месте, т.к. они небольшие то это лучше, чем много маленьких тем на форуме. Ссылки на них в попозже исправим.

    Хорошие заметки, делайте еще. У меня предложение про пространство System - лучше не стоит описывать все варианты делегата Action, одного достаточно, просто упомянуть, что есть еще такие.. Читатель поймет для чего и как использовать остальные по аналогии.


    Для связи [mail]
    19 сентября 2011 г. 6:45
  • Спасибо. Замечания учту.
    super_be
    19 сентября 2011 г. 15:00
  • Классы и прототипы

    Предыдущее | Оглавление | Следующее

    В JavaScript отсутствует классическая модель наследования — вместо неё используется прототипная модель, поверх которой можно реализовать классическое наследование. В Script# эта прототипная модель моделируется обычными классами C#.

    Создадим новый проект Script# и в нем простой класс «ExamplesClass», добавим в него поле «simpleField», свойство «SimpleProperty», конструктор и метод «Equals»:

    // ExamplesClass.cs
    //
    
    using System.Runtime.CompilerServices;
    
    namespace ScriptLibrary.Symple
    {
        /// <summary>
        /// Пример простого класса.
        /// </summary>
        /// <remarks>Зададим пространство имен «ScriptLibrary»</remarks>
        [ScriptNamespace("ScriptLibrary")]
        public class ExamplesClass
        {
            /// <summary>
            /// Поле.
            /// </summary>
            private string _simpleField;
    
            /// <summary>
            /// Свойство.
            /// </summary>
            public string SimpleProperty
            {
                get { return _simpleField; }
                set { _simpleField = value; }
            }
    
            /// <summary>
            /// Конструктор.
            /// </summary>
            /// <param name="simpleArgument">Входной параметр.</param>
            public ExamplesClass(string simpleArgument)
            {
                _simpleField = simpleArgument;
                if (SimpleProperty != null && SimpleProperty != simpleArgument)
                {
                    SimpleProperty = simpleArgument;
                }
            }
    
            /// <summary>
            /// Простой метод сравнивающий поле «_simpleField» с входным
            /// параметром «otherLine».
            /// </summary>
            /// <param name="otherLine">Входной параметр.</param>
            /// <returns>Результат выполнения метода.</returns>
            /// <remarks>Атрибут «PreserveCase» отменяет верблюжью нотацию
            /// при компиляции метода.</remarks>
            [PreserveCase]
            public bool Equals(string otherLine)
            {
                return string.Equals(_simpleField, otherLine, true);
            }
        }
    }

    Откомпилируем наш класс и посмотрим, что получилось:

    //! ScriptLibrary.debug.js
    //
    
    (function() {
    
    Type.registerNamespace('ScriptLibrary');
    
    ////////////////////////////////////////////////////////////////////////////////
    // ScriptLibrary.ExamplesClass
    
    ScriptLibrary.ExamplesClass = function ScriptLibrary_ExamplesClass(simpleArgument) {
        /// <summary>
        /// пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ.
        /// </summary>
        /// <param name="simpleArgument" type="String">
        /// пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
        /// </param>
        /// <field name="_simpleField" type="String">
        /// пїЅпїЅпїЅпїЅ.
        /// </field>
        this._simpleField = simpleArgument;
        if (this.get_simpleProperty() != null && this.get_simpleProperty() !== simpleArgument) {
            this.set_simpleProperty(simpleArgument);
        }
    }
    ScriptLibrary.ExamplesClass.prototype = {
        _simpleField: null,
        
        get_simpleProperty: function ScriptLibrary_ExamplesClass$get_simpleProperty() {
            /// <summary>
            /// пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
            /// </summary>
            /// <value type="String"></value>
            return this._simpleField;
        },
        set_simpleProperty: function ScriptLibrary_ExamplesClass$set_simpleProperty(value) {
            /// <summary>
            /// пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
            /// </summary>
            /// <value type="String"></value>
            this._simpleField = value;
            return value;
        },
        
        Equals: function ScriptLibrary_ExamplesClass$Equals(otherLine) {
            /// <summary>
            /// пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ пїЅ_simpleFieldпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ
            /// пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅotherLineпїЅ.
            /// </summary>
            /// <param name="otherLine" type="String">
            /// пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ.
            /// </param>
            /// <returns type="Boolean"></returns>
            return String.equals(this._simpleField, otherLine, true);
        }
    }
    
    
    ScriptLibrary.ExamplesClass.registerClass('ScriptLibrary.ExamplesClass');
    })();
    
    //! This script was generated using Script# v0.7.3.0

    Разберем этот пример подробнее. 


    super_be
    • Изменено super_be 24 сентября 2011 г. 13:41
    24 сентября 2011 г. 10:03
  • Сборка

    Предыдущее | Оглавление | Следующее

    Обратим внимание на то, что компилятор автоматически поместил скомпилированную сборку в анонимную обертку, тем самым выделив для нашей сборки свое специфическое глобальное пространство имен. Это дает преимущество в том, что переменные нашей сборки не будут перекрываться переменными другой сборки.

    //! ScriptLibrary.debug.js
    //
    
    (function() {
    ...
    })();
    
    //! This script was generated using Script# v0.7.3.0

    super_be
    • Изменено super_be 24 сентября 2011 г. 13:44
    24 сентября 2011 г. 10:06
  • Пространство имен

    Предыдущее | Оглавление | Следующее

    Внутри нашей сборки пространство имен моделируется через глобальный объект.

    Type.registerNamespace('ScriptLibrary');

    Обратите внимание на то, что наименование пространства имен класса отличается от пространства имен в конечном коде JavaScript

    // C# 
    namespace ScriptLibrary.Symple
    {
        [ScriptNamespace("ScriptLibrary")]
        public class ExamplesClass
        {
            ...
        }
    }

    JavaScript:  

    // JavaScript 
    ScriptLibrary.ExamplesClass.registerClass('ScriptLibrary.ExamplesClass');

    Такое возможно за счет задания специфических значений атрибутов класса.

    [ScriptNamespace("ScriptLibrary")]

    Атрибут определяет специфическое наименование пространства имени класса. Принимает один входной параметр: строку задающую наименование пространства имени.

     [GlobalMethods]

    Определяет глобальные методы. При этом класс должен быть определен как «static». Все методы этого класса будут представлены как высокоуровневые глобальные элементы, а конструктор как анонимная обертка. Такой класс не может содержать поля или события. 

    // C# 
    namespace ScriptLibrary
    {
        [GlobalMethods]
        public static class Examples
        {
            public static void ExamplesMethod()
            {
                ...
            }
    
            static Examples()
            {
                ...
            }
        }
    }

    JavaScript: 

    // JavaScript 
    window.examplesMethod = function ScriptLibrary_Examples$examplesMethod() {
        ...
    }
    
    
    (function () {
        ...
    })();

    [IgnoreNamespace]

    Атрибут определяет класс в глобальную область видимости. 

    // C# 
    namespace ScriptLibrary.Symple
    {
        [IgnoreNamespace]
        public class ExamplesClass
        {
            public ExamplesClass()
            {
                ...
            }
            ...
        }
    }

    JavaScript: 

    // JavaScript 
    ExamplesClass = function ExamplesClass(simpleArgument) {
        ...
    }
    ExamplesClass.prototype = {
        ...
    }
    
    ExamplesClass.registerClass('ExamplesClass');

     [Imported]

    Атрибут определяет импортируемые классы, т.е. классы, которые вызываются из уже готовых библиотек, но для которых не определено описание этих классов в Script#. Этот атрибут так же используется для моделирования возвращаемых JSON-объектов. При этом классы помеченные как импортируемые в конечную JavaScript сборку не помещаются, но в коде Script# к ним можно обращаться как к обычным классам.


    super_be
    • Изменено super_be 24 сентября 2011 г. 13:48
    24 сентября 2011 г. 10:16
  • Объявление класса

    Предыдущее | Оглавление | Следующее

    Компилятор Script# преобразует конструктор в функцию сценария, а сам класс в прототип. Функция «registerClass» регистрирует класс, что позволяет базовой системе типов выполнить необходимую инициализацию класса. При этом различные модификаторы доступа такие как internal, public, sealed, abstract и т.д. не проявляются в сгенерированном сценарии. Они реализованы на исходном уровне C# компилятором C#.

    ScriptLibrary.ExamplesClass = function ScriptLibrary_ExamplesClass(simpleArgument) {
    ...
    }
    ScriptLibrary.ExamplesClass.prototype = {
    ...
    }
    
    ScriptLibrary.ExamplesClass.registerClass('ScriptLibrary.ExamplesClass');

    super_be
    • Изменено super_be 24 сентября 2011 г. 13:51
    24 сентября 2011 г. 10:20
  • Свойства

    Предыдущее | Оглавление | Следующее

    Свойства моделируются парными методами доступа «get» и «set». При этом используется соглашение о присвоении имени префиксов «get_», и «set_»:

    // C# 
            public string SimpleProperty
            {
                get { return _simpleField; }
                set { _simpleField = value; }
            }

    JavaScript: 

    // JavaScript 
        get_simpleProperty: function ScriptLibrary_ExamplesClass$get_simpleProperty() {
            return this._simpleField;
        },
        set_simpleProperty: function ScriptLibrary_ExamplesClass$set_simpleProperty(value) {
            this._simpleField = value;
            return value;
        },
    

    super_be
    • Изменено super_be 24 сентября 2011 г. 13:54
    24 сентября 2011 г. 10:22
  • Позднее связывание свойств

    Предыдущее | Оглавление | Следующее

    К свойствам класса помимо прямого обращения (точечная нотация) можно обращаться с помощью методов позднего связывания запечатанного класса «Type». Чтобы задать свойство объекта необходимо вызвать метод «SetProperty», который принимает три параметра: собственно сам объект класса, наименование задаваемого свойства и его значение. Доступ к значению свойства обеспечивает метод «GetProperty», который принимает два входных параметра: сам объект и строковое наименование свойства.

    Создадим два экземпляра класса ранее нами созданного: 

    // C# 
    ExamplesClass boo = new ExamplesClass("Мама мыла раму");
    ExamplesClass foo = new ExamplesClass("А мыла ли раму мама?");

    JavaScript: 

    // JavaScript 
    var boo = new ScriptLibrary.ExamplesClass('\u041c\u0430\u043c\u0430 \u043c\u044b\u043b\u0430 \u0440\u0430\u043c\u0443');
    var foo = new ScriptLibrary.ExamplesClass('\u0410 \u043c\u044b\u043b\u0430 \u043b\u0438 \u0440\u0430\u043c\u0443 \u043c\u0430\u043c\u0430?');
    

    Явное обращение к свойствам: 

    // C# 
    foo.SimpleProperty = boo.SimpleProperty;

    JavaScript: 

    // JavaScript 
    foo.set_simpleProperty(boo.get_simpleProperty());

    Методы позднего связывания позволяют получить абсолютно такую же строку JavaScript

    // C# 
    Type.SetProperty(foo, "simpleProperty", Type.GetProperty(boo, "simpleProperty"));

    JavaScript: 

    // JavaScript 
    foo.set_simpleProperty(boo.get_simpleProperty());

    Здесь следует обратить внимание на тот факт, что наименование свойства мы передаем в «верблюжьей» нотации, т.к. компилятор переводит наименования свойств, полей и методов в эту нотацию.


    super_be
    • Изменено super_be 24 сентября 2011 г. 13:56
    24 сентября 2011 г. 10:27
  • Позднее связывание методов

    Предыдущее | Оглавление | Следующее

    Вызов метода средствами позднего связывания осуществляется посредством метода «InvokeMethod» запечатанного класса «Type», в который передается объект, наименование метода и список параметров передаваемых в метод. Вернемся к нашему примеру. Явно вызовем метод «Equals»:

    // C# 
    if (!boo.Equals(foo.SimpleProperty))
    {
        foo.SimpleProperty = boo.SimpleProperty;
    }

    JavaScript: 

    // JavaScript 
    if (!boo.Equals(foo.get_simpleProperty())) {
        foo.set_simpleProperty(boo.get_simpleProperty());
    }

    Вызовем наш метод через позднее связывание:

    // C# 
    if (!(bool) Type.InvokeMethod(boo, "Equals", foo.SimpleProperty))
    {
        foo.SimpleProperty = boo.SimpleProperty;
    }

    JavaScript: 

    // JavaScript 
    if (!boo.Equals(foo.get_simpleProperty())) {
        foo.set_simpleProperty(boo.get_simpleProperty());
    }

    Получили абсолютно идентичный код. Обратите на такую особенность: Здесь мы наименование метода передаем не в «верблюжьей» нотации, так как при определении метода в классе мы задали атрибут «PreserveCase», который отменяет эту нотацию.

    Для вызова глобального необходимо передать вместо объекта пустой объект null:

    // C# 
    Type.InvokeMethod(null, "examplesMethod");

    JavaScript: 

    // JavaScript 
    examplesMethod();
    

    super_be
    • Изменено super_be 24 сентября 2011 г. 13:59
    24 сентября 2011 г. 10:33
  • Перегрузка методов

    Предыдущее | Оглавление | Следующее

    Дополнительные параметры тесно связаны с перегрузками в C#. Script#, не поддерживает перегрузку по настоящему, так как во время ее выполнения может потребоваться сложная логика снятия омонимии.

    Однако Script# позволяет Вам объявлять несколько перегрузок на уровне C#, которые определяют альтернативные имена для определенного метода. Эти альтернативные объявления имен могут использоваться для создания дополнительных параметров семантики. Среди альтернативных имен хотя бы у одного метода должно быть тело реализации (обычно со всеми параметрами), а остальные альтернативные имена должны быть объявлены, как внешние и не должны иметь фактической реализации. Для перегруженного метода необходимо методу задать атрибут «AlternateSignature» и модификатор «extern», а тело метода заменить на точку с запятой.

    Для примера перегрузим метод «Equals» из нашего примера. Позволим ему осуществлять строгое и нестрогое сравнение двух строк, передачей логического значения в метод. Если передаваемый атрибут не задан, то будем считать сравнение не строгим, т.е. сравниваем две строки без учета регистра.

    // C# 
    [PreserveCase]
    [AlternateSignature]
    public extern bool Equals(string otherLine);
    
    [PreserveCase]
    public bool Equals(string otherLine, bool rigorous)
    {
        if (Script.IsNullOrUndefined(rigorous))
        {
            rigorous = true;
        }
        return string.Equals(_simpleField, otherLine, rigorous);
    }

    При этом компилятор в сборку внесет метод только с реализованным телом:

    // JavaScript 
    Equals: function ScriptLibrary_ExamplesClass$Equals(otherLine, rigorous) {
        if (ss.isNullOrUndefined(rigorous)) {
            rigorous = true;
        }
        return String.equals(this._simpleField, otherLine, rigorous);
    }

    Script# допускает реализацию только одной перегрузки, остальные должны быть декларированы. Поэтому, как правило, для реализации выбирают перегрузку с максимальным числом параметров, и, как правило, перегруженные параметры проверяются на существование.


    super_be
    • Изменено super_be 24 сентября 2011 г. 14:01
    24 сентября 2011 г. 10:35
  • Наследование

    Предыдущее | Оглавление | Следующее

    Во время регистрации класса объявляется вся цепочка наследования для производных классов. Система типов, реализованная в sscorlib.js гарантирует, что производный тип фактически наследует элементы родительского класса, и устанавливает цепочку, так, чтобы просмотр информации класса о базовом типе обеспечил ожидаемый результат. Конструктор производного класса вызывает конструктор базового класса:

    // C# 
    // ChildExamplesClass.cs
    //
    
    using System;
    using System.Collections.Generic;
    
    namespace ScriptLibrary.Symple
    {
        public class ChildExamplesClass : ExamplesClass
        {
            public ChildExamplesClass(string simpleArgument)
                : base(simpleArgument)
            {
                
            }
        }
    }

    JavaScript:

    // JavaScript 
    ScriptLibrary.Symple.ChildExamplesClass = function ScriptLibrary_Symple_ChildExamplesClass(simpleArgument) {
        ScriptLibrary.Symple.ChildExamplesClass.initializeBase(this, [ simpleArgument ]);
    }
    ...
    ScriptLibrary.Symple.ChildExamplesClass.registerClass('ScriptLibrary.Symple.ChildExamplesClass', ScriptLibrary.ExamplesClass);
    

    super_be
    • Изменено super_be 3 октября 2011 г. 16:26
    24 сентября 2011 г. 10:38
  • Циклы

    Предыдущее | Оглавление | Следующее

    Циклы в Script# преобразуются в циклы JavaScript практически без изменений. Script# позволяет использовать циклы для перечисления элементов любого объекта.

     

    // C# 
    int[] items = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int index = 0;
    
    while (index < items.Length)
    {
        Script.Alert(items[index]);
        index++;
    }
    
    for (int i = 0; i < items.Length; i++)
    {
        Script.Alert(items[i]);
    }
    

     

    JavaScript:

     

    // JavaScript 
    var items = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
    var index = 0;
    while (index < items.length) {
        alert(items[index]);
        index++;
    }
    for (var i = 0; i < items.length; i++) {
        alert(items[i]);
    }
    

     

    Однако простой оператор «foreach» преобразуется в оператор «while» JavaScript.

     

    // C# 
    int[] items = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    
    int sum = 0;
    foreach (int item in items)
    {
        sum += item;
    }
    Script.Alert(sum);
    

     

    JavaScript:

     

    // JavaScript 
    var sum = 0;
    var $enum1 = ss.IEnumerator.getEnumerator(items);
    while ($enum1.moveNext()) {
        var item = $enum1.current;
        sum += item;
    }
    alert(sum);
    

     

    Как правило, для перечисления «foreach» часто используют специальный набор объектов DictionaryEntry в Dictionary. Сам Dictionary представляет собой объект JavaScript.

     

    // C# 
    Dictionary userProperty = new Dictionary("Login", "super_be", "Password", "******");
    foreach (DictionaryEntry entry in userProperty)
    {
        if ((bool) Type.InvokeMethod(userProperty, "hasOwnProperty", entry.Key))
        {
            Debug.WriteLine(string.Format("User {0}: {1}", entry.Key, entry.Value));
        }
    }
    

     

    JavaScript:

     

    // JavaScript 
    var userProperty = { Login: 'super_be', Password: '******' };
    var $dict2 = userProperty;
    for (var $key3 in $dict2) {
        var entry = { key: $key3, value: $dict2[$key3] };
        if (userProperty.hasOwnProperty(entry.key)) {
            ss.Debug.writeln(String.format('User {0}: {1}', entry.key, entry.value));
        }
    }
    

     

    Здесь словарь «Dictionary» преобразуется в простой объект, по которому организован цикл. В процессе обхода создается новый объект представляющий элемент словаря. Здесь так же смоделировано использование метода hasOwnProperty, проверяющего свойство объекта и дальнейшее логирование его в консоль.

    Script# так же позволяет перечислять элементы любого объекта, создавая Dictionary из любого объекта коде C#.

     

    // C# 
    ExamplesClass examplesClass = new ExamplesClass("Мама мыла раму");
    foreach (DictionaryEntry entry in Dictionary.GetDictionary(examplesClass))
    {
        Script.Alert(entry.Key + ": " + entry.Value);
    }
    

     

    JavaScript:

     

    // JavaScript 
    var examplesClass = new ScriptLibrary.ExamplesClass('\ufffd\ufffd\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd \ufffd\ufffd\ufffd\ufffd');
    var $dict4 = examplesClass;
    for (var $key5 in $dict4) {
        var entry = { key: $key5, value: $dict4[$key5] };
        alert(entry.key + ': ' + entry.value);
    }
    

     


    super_be
    3 октября 2011 г. 16:16