Опубликован: 15.05.2013 | Доступ: свободный | Студентов: 265 / 9 | Длительность: 24:25:00
Специальности: Системный архитектор
Лекция 14:

Ключевые концепции компонентов WinRT

< Лекция 13 || Лекция 14: 12345 || Лекция 15 >
Аннотация: Из материалов этой лекции читатель ознакомится с основными сценариями использования компонентов и с методикой создания компонентов WinRT с использованием языков программирования C# и C++.
Ключевые слова: разделы

WinRT-компоненты, которые мы только что видели, показывают базовую структуру и действия подобных компонентов, но, очевидно, с ними связано еще очень много всего. Повторюсь, что так как рассмотрение всех подробностей выходит за рамки данного курса, я предлагаю вам посмотреть документацию, ссылки на которую даны в начале лекции. Здесь я просто хочу предложить вам краткую сводку наиболее важных моментов, после которой будут отдельные разделы по асинхронным методам и проекции WinRT в JavaScript.

Структура компонента

  • Выходные файлы компонентов на C#/VB –.NET-сборка с метаданными Windows представлены в виде файла .winmd; у C++ компонентов это DLL-файл с кодом и .winmd-файл с метаданными.
  • Приложения, которые используют компоненты, должны включать файлы.winmd/DLL в состав проектов, на них должны быть добавлены ссылки. Включать в состав проектов исходный код компонентов необязательно.
  • Классы компонентов, которые могут быть использованы из других языков, называются активирумыми (activatable) классами. В C# они должны быть маркированы как public sealed, в Visual Basic как Public NotInheritable, и в C++ как public ref sealed. Компонент должен иметь хотя бы один активируемый класс для того, чтобы им можно было пользоваться из других языков.
  • Классы могут иметь статические (static) члены (свойства и методы), которые можно использовать без создания экземпляра объекта этого класса.
  • Компоненты могут содержать множество общедоступных активируемых классов, так же как и дополнительных, внутренних классов. Все общедоступные классы должны располагаться в одном и том же корневом пространстве имен, которое имеет то же имя, что и файл метаданных компонента.
  • По умолчанию, все общедоступные классы в компоненты видимы из других языков. Класс может быть скрыт от JavaScript путем применения атрибута WebHostHiddenAttribute (http://msdn.microsoft.com/library/windows/apps/br206720.aspx) (то есть, перед объявлением класса должно идти [Windows.Foundation.Metadata.WebHostHidden] в C# или [Windows::Foundation::Metadata::WebHostHidden] в C++. Это применимо к классам, которые работают с пользовательским интерфейсом (подобная функциональность не может быть использована совместно с JavaScript, как, например, все пространство имен Windows.Xaml в WinRT) или к классам, функциональность которых совпадает со встроенными возможностями JavaScript (такими, как Windows.Data.Json).
  • Для того, чтобы узнать некоторые дополнительные сведения о структуре компонентов, смотрите следующие примеры из Windows SDK (все они используют WRL, смотрите врезку "Библиотека шаблонов C++ среды выполнения Windows (WRL)"):

Типы

  • Внутри компонента вы можете использовать собственные типы данных языка (то есть, .NET-типы и типы C++). На уровне интерфейса компонента (Application Binary Interface, или ABI), вы должны использовать WinRT-типы или собственные типы языка, которые совместимы с WinRT-типами. В противном случае их значения не смогут быть спроецированы в другие языки. В C++, типы WinRT существуют в пространстве имен Platform (http://msdn.microsoft.com/library/windows/apps/hh710417.aspx), посмотрите так же материал "Система типов (C++/CX)" (http://msdn.microsoft.com/library/windows/apps/hh755822.aspx). В C#/VB, они существуют в пространстве имен System, посмотрите материал "Сопоставление типов .NET Framework с типами среды выполнения Windows" (http://msdn.microsoft.com/library/windows/apps/hh995050.aspx)
  • Компоненты могут использовать структуры, созданные с помощью типов WinRT, которые проецируются в JavaScript как объекты со свойствами, соответствующими членам объекта struct.
  • Коллекции должны использовать специальные типы WinRT, которые находятся в Windows.Foundation.Collections (http://msdn.microsoft.com/library/windows/apps/windows.foundation.collections.aspx), такие, как IVector, IMap (и IMapView), и IPropertySet. Именно поэтому нам так часто встречаются векторы.
  • К массивам применимы специальные условия, так как их можно отправлять лишь в одном направлении, как мы видели в кратких руководствах. Таким, образом, каждый из них может быть маркирован либо как массив только для чтения, либо как массив только для записи. Смотрите материал "Передача массивов в компонент среды выполнения Windows" (http://msdn.microsoft.com/library/windows/apps/hh975353.aspx). У массивов так же есть ограничение на использование с асинхронными методами, так как выходной массив не возвращается вызывающему объекту при завершении асинхронной операции. Больше об этом мы поговорим в разделе "Реализация асинхронных методов" ниже.

Реализация компонентов

  • Создавая перегруженные методы, убедитесь, что арность (arity) (количество аргументов) у каждой из них различается, так как JavaScript не может определять перегруженные методы лишь по типу. Если вы создаете несколько перегрузок с тем же количеством аргументов, одна из них должна быть отмечена атрибутом DefaultOverloadAttribute (http://msdn.microsoft.com/library/windows/apps/windows.foundation.metadata.defaultoverloadattribute.aspx) для того, чтобы при использовании JavaScript-проекции было известно, какой из них нужно использовать.
  • Делегат (анонимная функция в определении JavaScript), это объект функции. Делегаты используются для событий, обратных вызовов и асинхронных методов. Объявление делегата ведет к определению сигнатуры функции.
  • Ключевым словом event отмечается общедоступный член специального типа делегата в виде событие. Делегаты события – сигнатура для обработчика – могут иметь тип (то есть, EventHandler<T>), что означает, что объект eventArgs для данного обработчика будет объектом заданного типа. Обратите внимание, что типизированные обработчики событий, наподобие этого, для поддержки проектции в JavaScript, требуют реализацию COM proxy/stub. Смотрите четыре примера, упомянутые в разделе "Структура компонента". Кроме того, смотрите материал "Использование C# и Visual Basic для работы с пользовательскими событиями и методами доступа к событиям в среде выполнения Windows" (http://msdn.microsoft.com/library/windows/apps/hh972883.aspx).
  • Выдача исключения: используя ключевое слово throw в C#, VB, и C++ вы вызовете новый экземпляр объекта с типом исключения в пространстве имен System (http://msdn.microsoft.com/library/windows/apps/hh454070.aspx). В C++ используйте throw ref new с одним из типов исключений в пространстве имен Platform namespace, например, Platform::InvalidArgumentException (http://msdn.microsoft.com/library/windows/apps/hh755794.aspx). Это отобразится в JavaScript со сведениями о стеке, в поле сообщения исключения. Действительное сообщение от компонента появлится в диалоговом окне исключений Visual Studio

Реализация асинхронных методов

Какими бы быстрыми не были процедуры, выполняемые на C# и C++, которые мы видели в разделе "Быстрый старт", факт заключается в том, что их исполнение может занимать более 50 мс при выполнении в потоке пользовательского интерфейса. Это – рекомендованный порог, достигнув которого, вы должны задуматься о том, чтобы сделать операцию асинхронной. Это означает исполнение кода в другом потоке, в итоге, пользовательский интерфейс не блокируется вовсе. Для того, чтобы показать основы, следующие разделы показывают, как реализовать асинхронную версию простой функции countFromZero , которую мы видели ранее, во врезке, где сравнивался управляемый и машинный код. Сначала мы реализуем это с помощью рабочего процесса, а потом – в C# и C++.

Для C#/VB и C++ имеется подробная документация по созданию асинхронных методов. В базовом материале, который мы уже упоминали, "Создание компонентов среды выполнения Windows в C# и Visual Basic" (http://msdn.microsoft.com/library/windows/apps/br230301.aspx) есть подраздел "Асинхронные операции", посвященный этому. В материале "Пошаговое руководство. Создание основного компонента среды выполнения Windows в C++ и его вызов из кода JavaScript" (http://msdn.microsoft.com/library/windows/apps/hh755833.aspx) есть подраздел "Добавление в класс асинхронных открытых методов". Есть материал "Создание асинхронных операций в C++ для приложений для Магазина Windows" (http://msdn.microsoft.com/library/hh750082.aspx). Кроме того, имеется серия сообщений в Блоге для разработчиков приложений для Windows 8, которые посвящены как приложениям, так и компонентам. В частности, это следующие: "Использование асинхронности в среде выполнения Windows для создания быстрых и гибких приложений" (http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/03/28/windows.aspx), "Подробное рассмотрение WinRT и await" (http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/05/04/winrt-await.aspx), "Предоставление задач .NET в виде асинхронных операций WinRT" (http://blogs.msdn.com/b/windowsappdev_ru/archive/2012/06/25/net-winrt.aspx). Попытка сравниться в глубине изложения с этими материалами была бы сопряжена с массой повторений, поэтому следующий раздел сосредоточен на создании асинхронной версии методов, работающих с пиксельными данными из кратких руководств и рассмотрению уроков, которые мы можем извлечь из опыта работы над ними.

Конкретный сценарий, с которым мы работаем – проводим преобразование пиксельных данных в оттенки серого и отправляем результат в элемент canvas – позволит выявить ряд сложностей, с которыми полезно будет поработать, и которые не упомянуты напрямую в другой документации. Это включает в себя сложности с передачей массивов между приложениями и компонентами, что представляет интересный шаблон проектирования, которые используется некоторыми API WinRT. Тем не менее, решение приводит нас к чему-то вроде тупика, из-за ограничений элемента HTML canvas. Это заставляет нас задуматься об альтернативах, что является хорошим упражнением, так как вы, вероятно, столкнетесь с другими сложностями в вашей собственной работе над компонентами.

< Лекция 13 || Лекция 14: 12345 || Лекция 15 >