Упаковка и развертывание ресурсов
Обновлен: Ноябрь 2007
Для упаковки и развертывания ресурсов в платформе .NET Framework используется модель "звезда". Центр в этой модели — основная сборка, которая содержит нелокализуемый исполняемый код и ресурсы для единственного языка и региона, называемого нейтральным или языком и регионом по умолчанию. Язык и регион по умолчанию являются резервными параметрами для приложения. Каждый луч звезды ведет к вспомогательной сборке, которая содержит ресурсы для одного языка и региона, но не содержит кода.
У этой модели несколько преимуществ:
После развертывания приложения в него можно последовательно добавлять ресурсы для новых языков и регионов. Так как разработка ресурсов для конкретных языков и регионов может занять продолжительное время, эта модель дает возможность сначала выпустить главное приложение, а в дальнейшем постепенно дополнять его ресурсами для других языков и регионов.
Вспомогательные сборки приложения можно обновлять и изменять без перекомпиляции всего приложения.
В приложение можно загружать только те вспомогательные сборки, которые содержат ресурсы, необходимые для конкретного языка. Такой подход существенно снижает затраты системных ресурсов.
Тем не менее, у этой модели существует ряд недостатков:
Необходимо управлять множеством наборов ресурсов.
Увеличиваются первоначальные затраты ресурсов на тестирование приложения, поскольку требуется проверять несколько конфигураций. Следует заметить, что в долгосрочной перспективе проще и дешевле протестировать одно основное приложение и ряд вспомогательных сборок, чем тестировать и сопровождать несколько параллельных версий на разных языках.
Соглашения об именовании ресурсов
В процессе упаковки ресурсов приложения им необходимо присваивать имена в соответствии с соглашениями об именовании, которые применяются в среде CLR. Среда выполнения идентифицирует ресурс с помощью подписи (имени) соответствующего языка и региона. Каждому языку и региону присваивается уникальное имя, которое представляет собой сочетание имени языка из двух строчных букв, и (при необходимости) имени региона из двух прописных букв, обозначающего даную страну или регион. Имя региона следует за именем языка через дефис (-). Например, "ja-JP" обозначает японский язык в Японии, "en-US" — английский в США, "de-DE" — немецкий в Германии (в отличие от немецкого в Австрии — "de-AT"). Полный список языков и регионов см. в разделе Класс CultureInfo.
Процесс использования резервных ресурсов
В звездообразной модели упаковки и развертывания ресурсов для поиска подходящих ресурсов используется процесс перехода к резервному ресурсу. Если пользователь приложения запрашивает набор ресурсов ResourceSet, который оказывается недоступен, то среда CLR просматривает иерархию языков и регионов в поисках резервного ресурса, который наиболее точно отвечает запросу пользователя, и только в крайнем случае генерирует исключение. На каждом уровне иерархии производится поиск, и, если подходящий ресурс найден, среда выполнения использует его. Если ресурс не найден, поиск продолжается на следующем уровне. Процесс перехода к запасному ресурсу осуществляется следующим образом.
В первую очередь среда выполнения проверяет глобальный кэш сборок на наличие сборки соответствующей приложению по языку и региональным параметрам.
Глобальный кэш сборок может хранить сборки ресурсов, которые используются несколькими приложениями. Это избавляет от необходимости включать конкретные наборы ресурсов в структуру каталогов для каждого разрабатываемого приложения. Если среда выполнения находит ссылку на сборку, она просматривает эту сборку в поисках требуемого ресурса. Если среда выполнения обнаруживает в сборке нужную запись, она использует запрошенный ресурс. Если она не находит записи, поиск продолжается.
Затем среда выполнения проверяет каталог выполняемой в данный момент сборки на наличие каталога, соответствующего запрошенному языку и региональным параметрам. Если каталог найден, среда выполнения ищет в нем допустимую вспомогательную сборку для запрошиваемого языка и региона. Далее она просматривает вспомогательную сборку в поисках запрошенного ресурса. Если ресурс обнаружен в сборке, среда выполнения использует его. Если ресурс не найден, поиск продолжается.
Затем среда выполнения снова просматривает глобальный кэш сборок, на этот раз в поисках родительской сборки запрошенного ресурса. Если родительская сборка присутствует в глобальном кэше сборок, среда выполнения ищет в ней ресурс.
Родительская сборка принимается в качестве подходящего резервного языка и региона. Родительские сборки считаются оптимальными кандидатами на эту роль, поскольку предоставление любых ресурсов является более желательным, чем порождение исключения. Этот процесс позволяет многократно использовать ресурсы. Включать ресурс на родительском уровне следует только в том случае, если дочерняя культурная среда не требует локализации запрошенного ресурса. Например, если заданы вспомогательные сборки для культурных сред "en" (нейтральный английский), "en-GB" (английский, используемый в Великобритании) и "en-US" (английский, используемый в США), то сборка "en" будет содержать общие термины, а в сборках "en-GB" и "en-US" достаточно переопределить только те термины, которые отличаются в этих языках.
Затем среда выполнения проверяет каталог текущей сборки на наличие родительского каталога. Если родительский каталог существует, среда выполнения ищет в нем допустимую вспомогательную сборку для родительского языка и региона. Если сборка найдена, среда выполнения просматривает ее в поисках запрошенного ресурса. Если ресурс обнаружен, он используется. Если ресурс не найден, поиск продолжается.
Далее среда выполнения просматривает родительские сборки по нескольким уровням, выполняя на каждом из них те же действия, что и на предыдущем шаге. У каждого языка и региона существует только одна родительская среда, которая, тем не менее, может обладать собственной родительской средой.
Если после просмотра первоначально заданного языка и региона и всех родительских сред ресурс не найден, используется ресурс стандартной (запасной) культурной среды. В .NET Framework версий 2.0 и выше можно определить вспомогательную (вместо основной) сборку в качестве конечного расположения запасных ресурсов. Чтобы определить вспомогательную или основную сборку в качестве конечного расположения запасных ресурсов, следует использовать NeutralResourcesLanguageAttribute с перечислением UltimateResourceFallbackLocation.
Примечание. Стандартный ресурс является единственным ресурсом, компилируемым вместе с основной сборкой. Если с помощью NeutralResourcesLanguageAttribute в качестве конечного расположения запасных ресурсов не задана вспомогательная сборка, в качестве такого расположения (конечного родительского объекта) используется основная сборка. Поэтому настоятельно рекомендуется всегда включать стандартный набор ресурсов в основную сборку. Это помогает избежать исключений. Стандартный файл ресурсов обеспечивает запасной вариант для всех ресурсов и гарантирует, что пользователю всегда будет предоставлен хотя бы один ресурс, даже если он не связан с определенной культурной средой.
В конечном итоге, если среда выполнения не находит ресурса для стандартного (резервного) языка и региона, порождается исключение, указывающее на то, что ресурс не найден.
Чтобы продемонстрировать поиск ресурса на примере, предположим, что пользователь запросил ресурс, локализованный для испанского языка (Мексика). В соответствии с вышеупомянутым соглашением об именовании ресурсов среда выполнения сначала просматривает глобальный кэш сборок в поисках сборки, соответствующей запрошенному языку и региону "es-MX". Не найдя такой сборки, среда выполнения ищет каталог "es-MX" в каталоге выполняемой в данной момент сборки. Если этот поиск также не приносит результатов, среда выполнения снова просматривает глобальный кэш сборок в поисках родительской сборки соответствующей резервному языку, в данном случае — "es" (испанский язык). Если родительская сборка не найдена, среда выполнения просматривает все возможные уровни родительских сборок для языка и региона "es-MX", пока не найдет соответствующий ресурс. Если ресурс не будет найден, среда выполнения использует ресурс для языка и региональных параметров по умолчанию.
Определение вспомогательной сборки в качестве конечного расположения запасных ресурсов
В .NET Framework версий 2.0 и выше можно при необходимости удалить ресурсы из основной сборки и задать вспомогательную сборку, соответствующую определенному языку и региону, в качестве конечного расположения запасных ресурсов. Для управления процессом использования запасного ресурса можно использовать атрибут NeutralResourcesLanguageAttribute. К классу NeutralResourcesLanguageAttribute добавляется новый конструктор, который принимает дополнительный параметр UltimateResourceFallbackLocation, определяющий расположение, из которого объект ResourceManager извлекает запасные ресурсы: основная или вспомогательная сборка.
В следующем примере показано применение атрибута на уровне класса.
[assembly: NeutralResourcesLanguageAttribute("de" , UltimateResourceFallbackLocation.Satellite)]
Для конечного расположения запасных ресурсов код вызывает ResourceManager для поиска ресурсов в подкаталоге "de" каталога выполняющейся в данный момент сборки.
Предлагаемые альтернативные методы упаковки
Финансовые или временные ограничения могут не позволить создать набор ресурсов для каждого региона, который поддерживает приложение. В такой ситуации можно разработать единственную вспомогательную сборку для родительского языка, которая будет использоваться для всех связанных с ней региональных параметров. Например, можно создать одну вспомогательную сборку для английского языка (en), которая будет вызываться пользователями при запросе англоязычных ресурсов для конкретного региона, и одну сборку на немецком (de) для пользователей, запрашивающих ресурсы немецкоязычной версии для определенного региона. Так, запросы ресурсов для немецкоязычной версии Германии (de-DE), немецкоязычной версии Австрии (de-AT) и немецкоязычной версии Швейцарии (de-CH) будут переданы во вспомогательную сборку для немецкого языка (de). Следует внимательно относиться к выбору стандартных ресурсов, которые будут компилироваться вместе с основной сборкой. Стандартные ресурсы представляют собой окончательные запасные варианты, поэтому в этом качестве следует использовать ресурсы, которые будут запрашиваться большинством пользователей создаваемого приложения. Хотя в таком решении будут задействованы ресурсы более общего характера, тем не менее это позволит существенно снизить затраты на локализацию приложения.