7 апреля 2013 г.

Вызов управляемого кода в WinJS. Часть 2

Всем привет! Сегодня мы продолжим говорить о работе с управляемым кодом при разработке Windows Store JavaScript приложений. В прошлой статье мы познакомились с ограничениями проекта Windows Runtime Component и рассмотрели самый простой пример вызова функции на C#.

В этой статье мы, в первую очередь, рассмотрим асинхронные вызовы между JavaScript и C#, которые де-факто являются основой взаимодействия с управляемым кодом. А также узнаем, как можно передавать сложные типы данных между вызовами, научимся использовать события и отлаживать наш код в Visual Studio.

Асинхронный вызов функций

Стоит отметить, что использовать какие-либо вызовы кроме асинхронных строго не рекомендуется. В принципе, в любом клиентском приложении (JS, Silverlight, WinForms) выполнение тяжелых операций в главном потоке ведет к снижению производительности и в конечном счете зависанию клиентского приложения.

Ниже приведен код класса в проекте Windows Runtime Component, который предоставит клиенту всего один метод:

   1:  public sealed class ManagementClass
   2:  {
   3:      public IAsyncOperation<string> GetHelloMessageAsync(string name)
   4:      {
   5:          return Task.Run(async () => await StartTask(name)).AsAsyncOperation();
   6:      }
   7:   
   8:      private Task<string> StartTask(string name)
   9:      {
  10:          return Task.Factory.StartNew(() => GetHelloString(name));
  11:      }
  12:   
  13:      private string GetHelloString(string name)
  14:      {
  15:          return "Hello " + name;
  16:      }
  17:  }

То есть, для каждого метода, который вы будете использовать на стороне WinJS необходимо написать три метода на C# для правильного «асинхронного» вызова. Согласитесь, немного накладно. Но, что делать, пока это единственный способ. Платформа и средства разработки появились сравнительно недавно, поэтому я уверен в следующих версиях мы увидим способы более удобного использования.

Пример вызова асинхронного метода клиентом приведен ниже:


   1:  var myClass = new WinJsDemo.Utilities.ManagementClass();
   2:  myClass.getHelloMessageAsync("Jack").then(
   3:      function (response) {
   4:          document.getElementById("content").innerHTML = response;
   5:      }
   6:  );

Передача сложных типов данных

Возможности классов сильно ограничены. Параметры функций и тип возвращаемого значения должны быть определены в библиотеке Windows Runtime. То есть, использовать можно только стандартные типы данных и коллекции этих типов соответственно. При передачи коллекций и простых типов из C# кода они будут автоматически преобразованы в соответствующие типы JavaScript. Схема преобразований основных типов приведена в таблице ниже:

Windows Runtime

.NET Framework

IIterable<T>

IEnumerable<T>

IVector<T>

IList<T>

IVectorView<T>

IReadOnlyList<T>

IMap<K, V>

IDictionary<TKey, TValue>

IMapView<K, V>

IReadOnlyDictionary<TKey, TValue>

IKeyValuePair<K, V>

KeyValuePair<TKey, TValue>

При разработке сложных приложений было бы удобно использовать собственные классы для передачи данных между средами. К сожалению, единственный способ это сделать – сериализовать класс в JSON строку и десериализовать строку при получении. На стороне JavaScript существуют методы JSON.parse и JSON.stringify, выполняющие функции сериализации, а вот в C# придется писать все самому, потому что подключить существующие библиотеки для работы с JSON к проекту, увы, не получится.


При разработке сложных приложений было бы удобно использовать собственные классы для передачи данных между средами. К сожалению, единственный способ это сделать – сериализовать класс в JSON строку и десериализовать строку при получении. На стороне JavaScript существуют методы JSON.parse и JSON.stringify, выполняющие функции сериализации, а вот в C# придется писать все самому, потому что подключить существующие библиотеки для работы с JSON к проекту, увы, не получится.


Использование событий

Одна из интересных особенностей, доступных при использовании управляемого кода – поддержка событий. Мы можем объявить событие в C# классе и подписать JavaScript функцию на это событие. Код на стороне C#:


   1:  public sealed class ManagementClass
   2:  {
   3:      public event EventHandler<MyEventArgs> TestEvent;
   4:          
   5:      public void RaiseEvent(string value)
   6:      {
   7:          if (TestEvent != null)               
   8:              TestEvent(this, new MyEventArgs { Value = value });
   9:      }
  10:  }
  11:   
  12:  public sealed class MyEventArgs
  13:  {
  14:      public string Value { get; set; }
  15:  }

Класс MyEventArgs помогает нам передавать собственные параметры события подписчикам. Обратите внимания, что его не нужно наследовать от EventArgs, как мы привыкли в обычном C#. Теперь посмотрим на использование события клиентом:


   1:  var myClass = new WinJsDemo.Utilities.ManagementClass();
   2:          
   3:  myClass.addEventListener("testevent", function (eventArgs) {
   4:      document.getElementById("content").innerHTML = eventArgs.value;
   5:  });
   6:  myClass.raiseEvent("Hello from event!");

Заметьте, что имя события переводится в нижний регистр. Впрочем, как и первый символ в имени всех методов.


Исключения и отладка управляемого кода

Объявлять и выбрасывать собственные исключения запрещено. Если модуль не перехватывает исключение – оно будет передано на сторону JavaScript и выброшено там. Стек трейс исключения будет доступен в объекте, перехваченным в блоке try-catch.

Visual Studio также предоставляет возможность отлаживать управляемый код в WinJS приложении. К сожалению, устанавливать точки остановки на стороне C# и на стороне JavaScript одновременно не возможно, только что-то одно. Переключаться между режимами отладки можно в свойствах проекта WinJS (Script Only / Management Only):

clip_image002

Спасибо за внимание. Надеюсь эта статья поможет вам полностью разобраться в аспектах использования управляемого кода при написании JavaScript приложений для Windows 8. Полезные ссылки по теме вы найдете ниже.


  1. Создание Windows Runtime компонента на языке C#
  2. Вызов компонента C# из JavaScript

Комментариев нет:

Отправить комментарий