Главная » Silverlight » Двоичные ресурсы

0

Приложение Silverlight фактически является набором файлов, упакованных в одном файле ZIP с расширением . хар. Файл ХАР содержит манифест (список файлов, исполь­зуемых в проекте), сборку приложения и ресурсы.

Ресурс ХАР — это отдельный файл, который можно сделать доступным в скомпили­рованном приложении. В ресурсы обычно включают изображения, аудио- и видеофай­лы, которые нужно отобразить в пользовательском интерфейсе приложения.

Ресурсы можно хранить в разных местах, поэтому иногда их чрезмерно усложня­ют, хотя в этом нет необходимости. Ниже перечислены места, в которых можно хра­нить ресурсы.

[1]    Сборка приложения. Файл ресурса внедряется в скомпилированный файл DLL проекта, например, SilverlightApplicationl .dll. В рабочей среде Visual Studio этот способ сохранения используется по умолчанию.

•       Пакет приложения. Файл ресурса сохраняется в архиве ХАР наряду со сборкой приложения. Его так же легко развернуть, но, по сравнению с предыдущим спо­собом, им легче управлять, потому что в пакете ХАР его можно заменить или от­редактировать, не компилируя приложение.

•       Исходный сайт. Файл ресурса хранится на сайте вместе с файлом ХАР. В этом случае развертывание существенно усложняется, потому что, кроме файла ХАР, нужно предоставить файл ресурсов. Однако разработчик получает возможность использовать ресурс другими способами, например в качестве изображения, ото­бражаемого на обычной веб-странице. Ресурс видео можно сделать доступным для потокового воспроизведения. Кроме того, при использовании данного спо­соба существенно уменьшается размер исходного загружаемого файла ХАР, что очень важно, если ресурс большой.

Возможны и другие способы хранения ресурсов. Например, ресурс можно хранить в других сборках, используемых приложением (см. далее). Этот способ облегчает управ­ление содержимым, используемым в разных приложениях Silverlight. Однако прежде чем обсудить этот способ, необходимо рассмотреть более популярные варианты, пере­численные выше. В следующих разделах подробно обсуждается каждый способ разме­щения ресурсов.

Примечание. Не путайте двоичные ресурсы с ресурсами XAML, которые рассматриваются в главе 2. Ресурс XAML — это объект, объявленный в разметке, а двоичный ресурс — это невыполняемый файл, вставленный в сборку или файл ХАР во время компиляции проекта.

Размещение ресурса в сборке приложения

Это стандартный подход, аналогичный используемому в приложениях .NET дру­гих типов (например, в приложениях WPF). Например, если нужно вывести изображе­ние в элементе Image, добавьте файл изображения в проект. По умолчанию программа Visual Studio присвоит свойству Build Action файла изображения значение Resource (рис. 6.11). Чтобы изменить значение Build Action любого файла, щелкните в поле свойства в окне Properties (Свойства). Появится стрелка раскрывающегося списка. Щелкните на ней и установите нужное значение.

Рис. 6.13. Файл ресурса grandpiano.jpg в архиве ХАР

При размещении ресурса в файле ХАР развертывание приложения выполняется так же легко, как и при внедрении в сборку, однако гибкость приложения повышается. Приложив дополнительные усилия, можно манипулировать файлом ресурса в архиве ХАР (например, обновлять графические файлы), не перекомпилируя приложение. Более того, если в файле ХАР хранятся несколько библиотечных сборок классов, все они могут

пользоваться файлами ресурсов, хранящимися в файле ХАР (этот способ используется редко, но он возможен). В целом, внедрение ресурса в сборку и размещение в пакете приложения — приблизительно равносильные методы.

Размещение ресурса в Интернете

Последний вариант: файлы ресурсов можно полностью удалить из приложения и сделать их доступными в Интернете. Приложение будет автоматически загружать их по мере необходимости. Благодаря тому, что Silverlight поддерживает адреса URI, для реализации этого метода нет необходимости писать дополнительный код, надстройка Silverlight сама загрузит нужные ресурсы.

Проще всего разместить файлы ресурсов на том же сайте, что и сборку Silverlight. Если применяется тестовый сайт ASP.NET, добавьте файл ресурса в папку ClientBin, в которой находится файл ХАР. При использовании тестовой страницы HTML добавьте файл ресурса в проект Silverlight и явно укажите программе Visual Studio, что с ним нужно делать. Выделите файл ресурса и присвойте свойству Build Action значение None, а свойству Copy to Output Directory — значение Copy Always.

Для обращения к ресурсу, размещенному в Интернете, используется тот же адрес URI, что и при размещении в пакете приложения. Ниже приведен пример относитель­ного URI.

clmage Source="/grandpiano.j pg"></Image>

Выполняя поиск ресурса, заданного таким образом, надстройка Silverlight сначала просматривает файл ХАР, а затем папку, в которой расположен файл ХАР. Следовательно, можно легко переключаться между разными методами размещения ресурса: в файле ХАР и в Интернете. Не нужно ни менять что-либо в приложении, ни перекомпили­ровать его. Достаточно удалить или добавить файл ресурса в файл ХАР или в папку приложения.

Ресурс не обязательно размещать на том же сайте, что и файл ХАР, хотя чаще все­го так и делают. При использовании абсолютного адреса URI ресурс можно извлечь из любого сайта.

<1шаде Source="http://www.mysite.com/Images/grandpiano.jpg">

</Image>

Примечание. При тестировании приложения, в котором есть файлы изображений с абсолютными адресами, возникает небольшая проблема. Элемент image не может обращаться к другим схемам. Это означает, что при выполнении приложения Silverlight непосредственно с жесткого диска с помощью простой тестовой страницы HTML оно не сможет извлечь изображение из Интернета. Для решения проблемы добавьте в проект тестовый сайт ASP.NET, как описано в главе 1.

Ресурсы, размещенные в Интернете, интерпретируются приложением немного ина­че, чем размещенные в приложении. Они не являются частью файла ХАР, поэтому они не сжаты. Если используется большой, легко сжимаемый файл (например, файл XML), размещенный в Интернете ресурс будет намного дольше загружаться (по крайней мере, для части пользователей). Еще более важен тот факт, что ресурсы, размещенные в Интернете, загружаются по требованию, когда приложение обращается к ним. Поэтому при большом количестве небольших ресурсов (особенно несжимаемых) предпо­чтительнее размещение в Интернете. В этом случае оно обеспечит малое время началь­ной загрузки приложения при небольших задержках на загрузку отдельных ресурсов.

Примечание. Очевидный недостаток всех трех указанных способов хранения ресурсов состоит в том, что в них используются фиксированные, неизменяемые, данные. Приложение не может изменить файл ресурса и сохранить измененную версию в сборке, файле ХАР или Интернете (теоретически можно было бы разрешить выгрузку измененных ресурсов на сайт, но это создало бы бреши в системе безопасности). Если все же нужно изменять ресурсы, наилучшее решение состоит в их сохранении в изолированном хранилище на жестком диске (см. главу 18) или на сервере с помощью веб-службы (см. главу 15).

Неудачная загрузка ресурса

Если в приложении применяется ресурс, размещенный в Интернете, всегда суще­ствует возможность того, что он окажется недоступным. Поэтому элементы, ожидаю­щие ресурсы, обычно предоставляют события, извещающие о том, что загрузка не может быть успешно завершена. Например, элемент Image предоставляет событие ImageFailed, а элемент MediaElement — событие MediaFailed.

Неудачная загрузка ресурса не является критической ошибкой. Если элемент Image не может загрузить рисунок, на экране всего лишь рисуется пустая рамка. Разработчик может предусмотреть в приложении какую-либо реакцию на неудачную загрузку ресурса.

Загрузка ресурса с помощью класса WebClient

К ресурсу, размещенному в Интернете, нельзя получить доступ с помощью рас­смотренного выше удобного метода Application.GetResourceStream(). Поэтому, если нужно использовать данные ресурса, размещенного в Интернете, причем для ресурса нет элемента, в котором можно задать адрес URI, вам придется проделать дополнитель­ную работу.

В этой ситуации для загрузки ресурса можно применить класс System. Net. WebClient, предоставляющий три основных метода. Наиболее полезен метод OpenReadAsync (). Он загружает файл как набор двоичных данных, которые затем предоставляются прило­жению в потоке. Метод DownloadStringAsync () загружает содержимое ресурса в одну строку. И наконец, метод CancelAsync () останавливает текущую загрузку.

Методы класса WebClient работают асинхронно. Событие DownloadProgressChanged можно использовать во время загрузки для выяснения количества полученных байтов. Завершение загрузки можно "поймать" с помощью события OpenReadCompleted или DownloadStringCompleted (в зависимости от метода загрузки). Когда загрузка заверше­на, приложение имеет возможность прочесть содержимое ресурса в потоке или строке. Методам класса WebClient присущи три существенных ограничения.

•       Класс WebClient не поддерживает "загрузку" из локальной файловой системы. Следовательно, чтобы применить класс WebClient, приложение должно выпол­няться через веб-сервер. В рабочей среде это несложно сделать, создав сайт ASP. NET, который будет хостироваться интегрированным веб-сервером (см. главу 1). Если открыть страницу Silverlight непосредственно в файловой системе и по­пытаться загрузить ресурс с помощью класса WebClient, будет сгенерировано исключение.

•       Класс WebClient не поддерживает относительные адреса URI. Чтобы получить правильный URI, вычислите URI текущей страницы, а затем добавьте к нему от­носительный URI, указывающий на ресурс.

•       Класс WebClient в каждый момент времени поддерживает только одну загрузку. Если попытаться передать второй запрос, когда выполняется первый, будет сге­нерировано исключение NotSupportedException.

Примечание. Существует еще один важный фактор: модель безопасности Silverlight. Если планируется применить класс WebClient для загрузки файла с другого веб-сервера (не того, который хостирует приложение), этот сервер должен явно разрешать кроссдоменные вызовы (см. главу 15).

Ниже приведен пример приложения, считывающего двоичные данные из файла ProductList.bin, как в предыдущем примере. Однако теперь файл ProductList.bin хо- стируется веб-сайтом и не входит в архив ХАР или сборку проекта. При тестировании данного примера с помощью сайта ASP.NET, нужно добавить на сайт файл ProductList. bin, а не проект Silverlight. Правильные конфигурационные параметры можно найти в кодах примеров, загружаемых для данной главы.

При щелчке на кнопке начинается загрузка. Обратите внимание на то, что стро­ка URI обрабатывается, а не передается непосредственно. Для получения правильного маршрута нужно создать полностью квалифицированный адрес URI на основе текущего адреса входной страницы, который можно извлечь из свойства Application.Host.

private void cmdRetrieveResource_Click(object sender,

RoutedEventArgs e)

{

// Создание полностью квалифицированного URI. // Предполагается, что файл расположен в корневой // папке сайта на один уровень выше папки ClientBin / / (иными словами, файл был добавлен на корневой // уровень сайта ASP.NET)

string uri = Application.Current.Host.Source.AbsoluteUri;

int index = uri.IndexOf("/ClientBin");

uri = uri.Substring(0, index) + "/ProductList.bin";

// Начало загрузки

WebClient webClient = new WebClient(); webClient.OpenReadCompleted += webClient_OpenReadCompleted; webClient.OpenReadAsync(new Uri(uri));

}

Теперь можно отреагировать на завершение загрузки. Загружаемые данные обраба­тываются как поток.

private void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)

{

if (e.Error != null) {

// Сюда нужно добавить код обработки ошибки // или средства плавной деградации

)

else {

Stream stream = е.Result;

BinaryReader reader = new BinaryReader(stream);

// Сюда нужно добавить код обработки содержимого ресурса

reader.Close ();

}

}

Для простоты код извлекает ресурс при каждом щелчке на кнопке. Однако в реаль­ном приложении необходимо применить более эффективное решение: сохранить извле­ченные данные в памяти, чтобы их не нужно было загружать каждый раз заново.

Необходимую для этого информацию предоставляют объект типа OpenRead- CompletedEventArgs и свойство Result. Выяснить, была ли загрузка отменена мето­дом CancelAcync (), можно с помощью свойства Cancelled. Если при загрузке произо­шла ошибка, объект исключения можно извлечь из свойства Error {при этом попытка прочесть другие свойства объекта OpenReadCompletedEventArgs приведет к возникно­вению исключения TargetlmvocationException). Можно также использовать перегру­женную версию метода OpenReadAsync (), которая принимает пользовательский объ­ект, извлеченный из свойства UserState. Однако необходимо учитывать ограничения, обусловленные тем, что класс WebClient в каждый момент времени загружает только один ресурс.

При загрузке большого файла рекомендуется вывести на экран индикатор прогрес­са, информирующий пользователя о том, что сейчас происходит. Для этого подключите обработчик к событию DownloadProgressChanged.

webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;

Ниже приведен код обработчика, который вычисляет процент загрузки и устанавли­вает значения индикатора прогресса и текстовой надписи.

private void webClient_DownloadProgressChanged (

object sender,

DownloadProgressChangedEventArgs e)

{

lblProgress.Text = "Загружено " +

e.ProgressPercentage.ToStringO + " %"; progressBar.Value = e.ProgressPercentage

}

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии