Модель адресации открытых соглашений об упаковке

 

Дэвид Мельцер и Андрей Шур
Microsoft Corporation

Июнь 2006 г.

Область применения:
   спецификации Open Packaging Conventions
   Microsoft Office 2007
   Microsoft Windows Vista
   Microsoft .NET Framework

Сводка: В этой статье представлен обзор модели адресации, используемой в соглашениях об открытой упаковке, в том числе способы обращения к пакетам и их частям, способы разрешения относительных ссылок в частях пакета и способы использования приложениями модели адресации пакетов с помощью платформа .NET Framework и классов. (16 печатных страниц)

Содержимое

Предисловие
Модель адресации
Поддержка программирования для URI pack:
Ссылки

Предисловие

В рамках разработки Office 2007 и Windows Vista корпорация Майкрософт представила соглашения об открытой упаковке. Эти соглашения описывают, как можно упорядочить содержимое в "пакете". Некоторые примеры содержимого включают документ, коллекцию носителей и библиотеку приложений. Пакеты объединяют все компоненты содержимого в один объект.

Текстовое приложение может использовать пакеты, например, для хранения страниц документа, необходимых шрифтов, изображений, диаграмм и заметок на страницах. Приложение для просмотра или управления документами может отображать только части содержимого в пакете. Приложения могут использовать формат на основе пакета, например XML Paper Specification (XPS), для отправки содержимого фиксированного макета и ресурсов на принтер.

В этой статье представлен обзор модели адресации, используемой в соглашениях об открытой упаковке, включая способы обращения к пакетам и их частям и способы разрешения относительных ссылок в частях пакета. В этой статье также рассматривается, как приложения могут использовать модель адресации пакетов с помощью классов платформа .NET Framework и платформа .NET Framework 3.0. Эта статья написана в основном для разработчиков приложений, которые будут обрабатывать, создавать или использовать пакеты.

Полные нормативные сведения, необходимые для реализации модели адресации пакетов, см. в спецификации для соглашений об открытой упаковке. В пакетах SDK для платформа .NET Framework 3.0 и .NET содержатся дополнительные сведения о рассматриваемых классах и методах.

В материалах, представленных в этом обзоре, предполагается базовое знание спецификации URI. В соответствии с RFC 3986 используются следующие термины: URI, ссылка на URI, компонент схемы, компонент центра, компонент пути, путь-абсолютный и относительная ссылка. Термин URI всегда обозначает абсолютную форму универсального кода ресурса (URI) — компонент схемы присутствует, а все остальные компоненты соответствуют грамматике, относящейся к конкретной схеме. Используемый здесь термин addressable указывает, что существует универсальный код ресурса (URI), который идентифицирует ресурс.

Модель адресации

Соглашения об открытой упаковке определяют логическую модель для упорядочения содержимого и ресурсов пакета и предоставляют сопоставление этой логической модели с физическим представлением на основе ZIP, XML и других открытых технологий.

Логическая модель упаковки , описанная в открытых соглашениях об упаковке, определяет абстракцию пакета, содержащую коллекцию частей. Части могут иметь связи друг с другом, а пакет может иметь связи с частями. Модель упаковки указывает, как части пакета именуются, ссылаются на них и связаны с ними. Модель адресации, определенная в соглашениях, является основой для возможности ссылаться на ресурсы частей и получать их в пакете.

Ресурсы адресуемого пакета

Экземпляр пакета в целом является адресуемым ресурсом, как и каждая часть, хранящаемая в экземпляре пакета.

Обращение к пакету как к единику

Приложения могут использовать универсальный код ресурса (URI) с любой схемой (например, "http:", "ftp:" и т. д.) для обращения к пакету как единое целое, получив поток битов, составляющих весь пакет.

Приложения также могут обращаться к пакету с помощью схемы URI "pack:", определенной в соглашениях об открытой упаковке. Эта схема указывает, что полный универсальный код ресурса (URI), определяющий пакет, хранится в компоненте центра URI "pack:" в закодированной форме.

Пример: обращение к пакету

Ресурс пакета обращается с помощью URI "http:" и "pack:" (соответственно) в следующих примерах:

http://www.site.com/windows/p1.xps

pack://http%3a,,www.site.com,windows,p1.xps/

Тип MIME приобретенного ресурса пакета указывает на формат файла пакета. Например, это может быть формат документа XPS (XPS), формат Office Open XML (.docx) или другой формат, соответствующий соглашениям об открытой упаковке.

По различным причинам (например, повышению производительности) приложения могут использовать URI, характерный для своего домена, в качестве компонента центра URI "pack:". Такой универсальный код ресурса (URI) разрешается только в контексте данного приложения. Метод программирования, используемый для таких URI конкретного приложения, описан далее в разделе "PackageStore".

Адресация частей в пакете

Для обращения к частям в пакете используются URI pack:. Структура универсального кода ресурса (URI) pack:, который адресует часть, выглядит следующим образом: pack://< путь проверки подлинности><>

Пример: адресация частей

pack://http%3a,,www.site.com,windows,p1.xps/fonts/arial.ttf адресует часть с именем /fonts/arial.ttf в пакете, адресуемой http://www.site.com/windows/p1.xps.

Компонент центра содержит кодированный универсальный код ресурса (URI) всего пакета; Компонент path содержит имя части в этом пакете. Имена частей соответствуют грамматике, определенной для компонента URI абсолютного пути ([2], раздел 3.3), с некоторыми дополнительными ограничениями ([1], раздел 2.1.1.1).

Пример: Имена частей

/documents/doc1.xaml

/pages/page4.xaml

/fonts/arial.ttf

Имена частей — это строки ASCII без учета регистра. Все части пакета имеют уникальные имена.

Использование идентификаторов фрагментов для ссылок на части

Некоторые приложения, использующие соглашения об открытой упаковке, могут ссылаться на часть с помощью URI блока пакета, отличного от "pack:", с идентификаторами фрагментов, зависящими от формата.

Пример. Использование URI, отличного от "pack:", для ссылки на часть

URI http://www.site.com/windows/p1.xps\#15 используется для ссылки на часть, представляющую страницу 15 в документе p1.xps ([3], разделы 9.2.2 и 9.2.3).

Хотя это допустимо и в некоторых сценариях полезно иметь URI, отличные от "pack:", ссылаться на части, такие URI нельзя использовать в качестве базовых URI для разрешения относительных ссылок в содержимом части.

Ссылки на записи в частях

Часть является наиболее детализированным ресурсом в пакете. Однако приложениям может потребоваться ссылаться на записи в содержимом части. Для некоторых типов контента на записи можно ссылаться с помощью идентификаторов фрагментов ([2], раздел 3.5). В соглашениях об открытой упаковке идентификаторы фрагментов не указываются. Приложения, использующие идентификаторы фрагментов, отвечают за их правильную обработку.

Пример. Ссылки на записи в частях

pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml#//[@Id="A012"] относится к набору XML-узлов в содержимом части с именем /pages/page1.xaml и атрибутом Id со значением A012.

Вложенные пакеты

Пакеты могут быть вложенными. Часть пакета может содержать содержимое любого типа, включая весь пакет. К частям вложенного пакета можно обращаться с помощью универсального кода ресурса (URI) pack:" с компонентом центра, который указывает на часть, содержащую этот вложенный пакет ([1], приложение D.3).

Пример: адресация частей во вложенных пакетах

Пакет, расположенный в , http://www.site.com/package содержит часть с именем /nested-package

,

адресуется пакетом URI pack ://http%3a,,www.site.com,package/nested-package.

Часть, к которой обращается предыдущий URI, содержит единицу пакета, которая содержит часть с именем /p1.xaml.

Адрес этой части во вложенном пакете выглядит следующим образом:

pack://pack%3a,,http:%253a%2c%2cwww.site.com%2cpackage,nested-package/p1.xaml.

Ссылки в содержимом части

Части с определенными типами содержимого, например XML, могут содержать ссылки на URI. Ссылки на URI могут быть URI или относительными ссылками. Ссылки на URI могут быть представлены в содержимом строками Юникода. Приложения, разрешающие такие ссылки URI, должны преобразовать строки в форму URI ([4], раздел 3.1).

Относительная ссылка — это URI, выраженный относительно базового URI содержимого, содержащего ссылку. Базовым универсальным кодом ресурса (URI) по умолчанию для содержимого части является URI pack:, адресуя часть.

Пример: базовый URI

Базовый URI для части с именем /pages/page1.xaml в пакете, к которым http://www.site.com/windows/p1.xps обращается, выглядит следующим образом:

pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml.

Если для разрешения относительных ссылок в записях содержимого части требуется альтернативный базовый URI, приложение должно явно указать альтернативный. Определенные типы контента предоставляют определенные способы указания альтернативного базового URI. Например, XML использует атрибут xml:base, HTML — базовый<> элемент, а Open Packaging Conventions — атрибут TargetMode для элементов Relationship.

Использование URI "pack:" части в качестве базового URI для относительной ссылки гарантирует, что указанный ресурс будет частью того же пакета ([2], раздел 5.2), если относительная ссылка не находится в редко используемой форме сетевого пути (то есть относительная ссылка, начинающаяся с "//").

Пример. Разрешение относительной ссылки

Относительная ссылка .. /.. /page2.xaml в части, адресованной как pack://http%3a,,www.site.com,windows,p1.xps/pages/page1.xaml , разрешается в pack://http%3a,www.site.com,windows,p1.xps/page2.xaml, адресуя часть с именем /page2.xaml.

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

Пример. Обращение к извлеченным ресурсам

В содержимом части с именем /doc1/pages/page1.xaml относительная ссылка /page2.xaml адресует часть с именем /page2.xaml, а относительная ссылка ./page3.xaml — часть с именем /doc1/pages/page3.xaml.

После извлечения частей /doc1/pages/page1.xaml, /doc1/pages/page3.xaml и /part2.xaml в файлы с именами file:///c:/mydocs/doc1/pages/page1.xaml, file:///c:/mydocs/doc1/pages/page3.xaml и file:///c:/mydocs/page2.xaml (соответственно), относительная ссылка ./page3.xaml адресует файл file:///c:/mydocs/doc1/pages/page3.xaml, который ожидается; Однако относительная ссылка /page2.xaml теперь обращается к файлу с именем file:///page2.xaml.

Относительные ссылки в отношениях

Соглашения о открытой упаковке определяют соединения между исходной и целевой частями в пакете как связи ([1], раздел 1.3).

Связи группируются и хранятся на основе их источников. Часть связей содержит связи, которые возникают в той же исходной части. Каждая связь описывается XML-элементом в содержимом этой части связей. Часть связей однозначно связана с этой исходной частью (и наоборот), используя определенное соглашение об именовании для части связей.

Базовым URI по умолчанию для URI, указанных в каждом элементе Relationship, является URI "pack:" исходной части ([1], раздел 1.3.5). Атрибут TargetMode элемента Relationship указывает базовый URI для указанной связи.

Пример: элемент Relationship

Элемент в части связей, который определяет связь между исходной частью с именем /pages/page1.xaml и целевой частью /fonts/arial.ttf в том же пакете, может выглядеть следующим образом:

<Тип связи="https://schemas.microsoft.com/xps/2005/06/restricted-font"

TargetMode="Internal" Id="A123" Target=".. /fonts/arial.ttf"/>

Внутреннее значение атрибута TargetMode указывает, что базовый универсальный код ресурса (URI) элемента Relationship используется по умолчанию для содержимого части связей и совпадает с URI "pack:" исходной части связей. В предыдущем примере базовым URI для элемента Relationship является универсальный код ресурса (URI) pack:" части /pages/page1.xaml .

Связи также могут быть нацелены на внешние ресурсы относительно расположения всего пакета.

Пример. Связь с внешним целевым объектом

Для пакета, расположенного в file:///c:/office12/sample.docx, XML-элемент

<Relationship Id="rId9"

Type="https://schemas.microsoft.com/office/2006/relationships/image"

Target="Icon.JPG" TargetMode="External"/>

определяет связь, ориентированную на файл file:///c:/office12/icon.jpg.

Значение External атрибута TargetMode указывает, что связь должна быть нацелена на ресурс за пределами пакета. Если атрибут Target содержит относительную ссылку, требуется базовый универсальный код ресурса (URI). Базовым универсальным кодом ресурса (URI) для этого элемента связи должен быть универсальный код ресурса (URI) всего пакета.

Делегирование ссылок на связи

Некоторые форматы на основе пакетов могут избегать использования ссылок URI в содержимом, делегируя ссылки на связи. Этот метод делегирования основан на использовании уникальных значений Id для каждого элемента Relationship для сопоставления относительных ссылок в содержимом части с соответствующими связями.

Пример. Сопоставление относительных ссылок в содержимом части со связями

Пакет, расположенный в file:///c:/office12/sample.docx , содержит часть с именем /word/document.xml , которая содержит

<a:blip relEmbed="rId6" relLink="" w="0" h="0"/>.

Часть связей, присоединенная к этой части, содержит элемент

<Relationship Id="rId6"

Type="https://schemas.microsoft.com/office/2006/relationships/image"

TargetMode="Internal" Target="media/image1.jpeg"/>.

Это связывает элемент с частью с именем /word/media/image1.jpeg.

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

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

Поддержка программирования для URI pack:

Приложения, создающие и (или) использующие пакеты, будут работать с адресами пакетов и частей и разрешать относительные ссылки в содержимом частей. платформа .NET Framework 3.0, которая предоставляет набор управляемых API нового поколения, предоставляемых корпорацией Майкрософт, включает классы, поддерживающие модель адресации Open Packaging Conventions. Эти классы позволяют приложениям создавать и анализировать ссылки, а также получать ресурсы пакета. Класс PackUriHelper используется для упрощения обработки URI "pack:". Класс PackWebRequest используется для получения ресурсов, адресованных с помощью URI "pack:".

В этом разделе показаны функции, выполняемые этими службами при составлении, анализе и разрешении ссылок.

Предоставление доступа к службам пакетов

Чтобы использовать классы служб упаковки, необходимо установить платформа .NET Framework версии 3.0 (или более поздней). Классы можно найти в пространстве имен System.IO.Packaging .

Перед использованием System.Uri для операций, в которых используются URI pack:, необходимо зарегистрировать схему URI pack:для домена приложения. Самый простой способ зарегистрировать схему URI "pack:" — вызвать любой метод класса PackUriHelper . Схему также можно зарегистрировать без вызова вспомогательного класса с помощью метода UriParser.Register , как показано в следующем примере. Однако для использования этого метода требуются разрешения безопасности.

Пример. Регистрация схемы URI "pack:"

//To register the "pack:" URI scheme without calling PackUriHelper

UriParser.Register(new GenericUriParser
   (GenericUriParserOptions.GenericAuthority),
      "pack", -1);

Получение URI "pack:" целевого ресурса

При использовании пакета весь пакет или по одной его части можно получить как объект . В любом случае метод PackUriHelper.Create можно использовать для создания универсального кода ресурса (URI) пакета или части pack:. Затем этот URI pack:передается в метод PackWebRequest , чтобы получить ресурс. PackWebRequest более подробно рассматривается в следующем разделе, "Получение ресурсов пакета с помощью PackWebRequest".

Распространенный пример использования классов PackUriHelper и PackWebRequest для поддержки использования пакета подробно описан в следующих шагах. Если URI пакета и URI части известны, приложение может:

  1. Создайте URI "pack:" из URI пакета и части URI с помощью PackUriHelper.
  2. Получите поток битов, вызвав PackWebRequest.
  3. Загрузите содержимое части и выполните синтаксический анализ, чтобы получить относительные ссылки.
  4. Разрешите эти относительные ссылки на базовый URI части (URI "pack:", составленный на шаге 1).
  5. Используйте System.Uri для разрешения относительных ссылок и PackWebRequest для получения указанных ресурсов.

Создание URI "pack:" для требуемого пакета

URI "pack:" пакета можно создать с помощью метода PackUriHelper.Create .

Пример: PackUriHelper.Create

//Given the URI for a package
Uri packageUri = new Uri("http://www.newsdocs.com
               /local/today.container");

//Use the Create method to create a "pack:" URI from a non-"pack:" URI
Uri packUri = PackUriHelper.Create(packageUri);

//The resulting packUri value is
//"pack://http%3a,,www.newsdocs.com,local,today.container/"

Созданный URI "pack:" передается в PackWebRequest , чтобы получить ресурс пакета.

Создание универсального кода ресурса (URI) pack:" для требуемой части

URI "pack:" части можно создать с помощью метода PackUriHelper.Create .

Пример: PackUriHelper.Create

//Given the URI for package 
Uri packageUri = new Uri("http://www.newsdocs.com
               /local/today.container");

//Given the URI for a part
Uri partUri = new Uri("/sports.xml", UriKind.Relative);

//Use the PackUriHelper.Create method to create a "pack:" URI

Uri packUri = PackUriHelper.Create (packageUri, partUri);

//The resulting packUri value is
//"pack://http%3a,,www.newsdocs.com,local,today.container/sports.xml"

Созданный URI "pack:" передается в PackWebRequest , чтобы получить ресурс части.

Разрешение относительных ссылок

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

Относительная ссылка в содержимом части разрешается по базовому URI части в URI "pack:" целевой части. URI "pack:" целевой части передается в PackWebRequest , чтобы получить ресурс части из пакета. Имя целевой части, производное от URI "pack:" целевой части, также можно использовать для получения целевой части путем передачи имени части в метод Package.GetPart .

При разрешении относительных ссылок на целевые части может быть несколько путей, которые может принимать разрешение, в зависимости от того, какие сведения доступны в начале, а также от того, открыт ли пакет (или может быть открыт). Ниже приведены два из этих путей:

  • В начале:

    1. Известен универсальный код ресурса (URI) "pack:" части, содержащей ссылку.
    2. Пакет не открыт.
    //Given the "pack:" URI for the part "/files/fixeddoc.xaml"
    //packUri =
    // "pack://http%3a,,www.newsdocs.com,local,today.container
    // /files/fixeddoc.xaml"
    
    //The part "/files/fixeddoc.xaml" contains 
    //the relative reference "../images/1.jpg"
    
    Uri relativeReference = new Uri("../images/1.jpg", 
                      UriKind.Relative);
    
    //Use System.Uri to directly obtain the absolute target URI
    
    Uri targetPackUri = new Uri(packUri, relativeReference);
    
    //The value of the resulting targetPackUri is 
    //"pack://http%3a,,www.newsdocs.com,local,today.container
    // /images/1.jpg"
    
    //Now another PackWebRequest can be made using 
    //this targetPackUri value.
    
  • В начале:

    1. Известное имя части, содержащей ссылку.
    2. Пакет открыт.
    //Given "package" as the current instance of the Package class.
    //Given the relative reference = "../../images/1.jpg"
    
    Uri relativeReference = new Uri("../../images/1.jpg", 
                      UriKind.Relative);
    
    //Given the URI of the part that contains the relative reference
    
    Uri partUri = new Uri("/files/fixeddoc.xaml");
    
    //Use PackUriHelper.ResolvePartUri to obtain the resolved part URI 
    //of the target based on the part URI above and the relative 
    //reference in that part
    
    Uri targetPartUri = PackUriHelper.ResolvePartUri
                   (partUri, relativeReference);
    
    //The resulting targetPartUri value is "fixeddoc.xaml"
    //Now use the package.GetPart method to obtain the target part
    
    PackagePart packagePart = package.GetPart(targetPartUri);
    

Предоставление имен частей для класса package

После открытия пакета класс Package полезен для добавления частей в пакеты, получения и удаления частей. Методы класса Package , такие как Package.AddPart, Package.DeletePart и Package.GetPart, принимают часть URI в качестве параметра. Метод PackUriHelper.CreatePartUri можно использовать для создания допустимого имени части из ссылки, которая относится к базовому URI пакета.

Пример: PackUriHelper.CreatePartUri

//Given a URI

Uri partUri = PackUriHelper.CreatePartUri 
            (new Uri "files/a.xaml",UriKind.Relative))

//The URI will be checked for validity, and a leading slash
//will be added. The resulting partUri value is "/files/a.xaml"

Служба для создания относительных ссылок

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

Пример. Пример GetRelativeUri

//Given the URI of the source part

Uri sourcePartUri = new Uri("/tiles/pages/a.xaml", UriKind.Relative);

//Given the URI of the target part

Uri targetPartUri = new Uri("/images/event1/1.jpg", UriKind.Relative);

//Use PackUriHelper.GetRelativeUri to generate the relative reference
//that will be placed in the content of the source part.

Uri relativeReference = PackUriHelper.GetRelativeUri
               (sourcePartUri, targetPartUri);

//The resulting relativeReference value is "../../images/event1/1.jpg"

Получение ресурсов пакета с помощью PackWebRequest

Приложения могут получать пакеты и компоненты ресурсов с помощью Класса PackWebRequest, производного от System.Net.WebRequest. PackWebRequest возвращает ресурс, к которым обращается заданный универсальный код ресурса (URI) pack:.

Как правило, инициализация PackWebRequest для универсального кода ресурса (URI) pack:" состоит из следующих этапов.

  1. Проверяется грамматика URI pack:.
  2. Компонент центра извлекается из URI "pack:" и проверяется, соответствует ли он грамматике для абсолютного URI.
  3. Если компонент пути для URI "pack:" пуст:
  • Поток пакета получается для компонента центра и возвращается вызывающей объекту.

    В противном случае, если компонент пути не пуст:

    1. Открытый пакет получается для ресурса, определяемого компонентом центра. В зависимости от набора CachePolicyPackWebRequest либо получает открытый пакет из PackageStore, либо создает внутренний WebRequest для ресурса пакета и открывает пакет из возвращенного потока пакета.
    2. Часть получается с помощью компонента пути URI "pack:" в качестве имени части.
    3. Поток части получается и возвращается вызывающей объекту.

PackWebResponse.GetStream возвращает поток битов, представляющий либо весь пакет ( поток пакета), либо одну часть пакета ( поток частей).

В отличие от большинства потоков WebResponse, поток пакета можно искать с помощью Stream.Seek. Поток пакета можно использовать для создания объекта пакета.

При работе с ресурсом пакета по протоколу http: , PackWebRequest поддерживает последовательную загрузку частей, т. е. возможность получения ресурсов части в произвольном порядке без загрузки всех данных в пакете вплоть до данных части.

PackWebRequest предоставляет только средства для потребления ресурсов. Его нельзя использовать для отправки или отправки данных на сервер.

В настоящее время PackWebRequest не поддерживает асинхронные операции (например, BeginGetResponse), а также Не поддерживает вложенные пакеты (описанные выше в разделе "Адресация частей в пакете").

The PackageStore

При загрузке пакетов с частями, содержащими многочисленные ссылки на другие части, можно сократить время отклика на запросы ресурсов и сократить сетевой трафик с помощью PackageStore. PackageStore — это локальный словарь приложений ссылок на открытые пакеты. Каждый пакет, зарегистрированный в PackageStore , определяется значением URI ключа.

PackageStore позволяет PackWebRequest получать ресурсы по мере необходимости из пакета, не выполняя серверный запрос каждый раз, когда требуется другой ресурс из этого пакета.

PackageStore не изменяется автоматически в результате вызова PackWebRequest— он должен быть явно изменен. Для добавления или удаления ссылок для открытия пакетов в PackageStore используются два открытых метода: Package.AddPackage и Package.RemovePackage.

Политика кэша по умолчанию (CacheIfAvailable), заданная в PackWebRequest , приводит к тому, что класс пытается использовать PackageStore для получения пакета. PackWebRequest можно принудительно игнорировать содержимое PackageStore при получении ресурсов, задав для политики кэша значение BypassCache, как описано в следующем разделе "Политики кэша".

При получении битов пакета или части в соответствии с политикой кэширования по умолчанию PackWebRequest сначала проверяет PackageStore , чтобы проверить, зарегистрирован ли пакет с ключом, равным компоненту центра URI "pack:". Если PackageStore не содержит пакет для ключа, PackWebRequest создаст внутренний WebRequest для скачивания ресурса с помощью компонента центра URI "pack:".

Политики кэша

Политики кэша определяют правила, используемые для определения возможности заполнения запроса ресурса с помощью кэшируемой копии ресурса.

При использовании PackWebRequest существует два уровня политики кэша, которые можно явно задать. Политику кэша можно задать для самого PackWebRequest , управляя взаимодействием с PackageStore. Кроме того, можно задать политику кэша для кэша, управляемого внутренним WebRequest. Доступ к внутреннему webRequest можно получить с помощью PackWebRequest с помощью PackWebRequest.GetInternalRequest().

Политика кэша, заданная во внутреннем WebRequest , не будет действовать, если для параметра PackWebRequest.CachePolicy задано значение CacheOnly, что приводит к получению ресурса пакета из PackageStore.

PackWebRequest.CachePolicy поддерживает подмножество политик, как показано ниже, из-за конкретных возможностей PackageStore.

Таблица 1. Политики PackWebRequest.CachePolicy

CachePolicy Описание
BypassCache Игнорировать записи PackageStore с соответствующим универсальным кодом ресурса (URI).
CacheOnly Учитывайте только записи PackageStore (никогда не создавайте WebRequest для запроса данных на сервере).
CacheIfAvailable Проверьте PackageStore и используйте любой пакет, если он найден; в противном случае выполните сетевой запрос к ресурсу, указанному URI пакета (внутренний URI "pack:"). Это значение по умолчанию.

Для PackWebRequest установка всех остальных значений CachePolicy приводит к webException.

Последовательная загрузка

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

Последовательная загрузка основана на выполнении запросов к ресурсам в диапазоне байтов, как определено в протоколе http:1.1. Этот механизм использует формат ZIP-файла, используемый для хранения пакетов в физической форме, так как формат ZIP-архива хранит важную информацию в "центральном каталоге" в физическом конце файла.

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

Службы для оценки и декомпосирования URI

Определение имен частей связи, возвращаемых классом пакета

При управлении коллекцией частей, полученной с помощью метода Package.GetParts , можно определить части связи, чтобы их можно было обрабатывать отдельно от других частей. PackUriHelper.IsRelationshipPartUri используется для определения того, является ли часть частью связи.

Пример: PackUriHelper.IsRelationshipPartUri

//Given the URI for a part

Uri partUri = new Uri("/_rels/sports.rels", UriKind.Relative);

bool isRelationshipPart = PackUriHelper.IsRelationshipPartUri(PartUri);

//The resulting isRelationshipPart value is "TRUE"

Для работы с именами частей связи доступны два других метода PackUriHelper . PackUriHelper.GetRelationshipPartUri возвращает имя части связи по имени исходной части. PackUriHelper.GetSourcePartUriFromRelationshipPartUriUri возвращает имя исходной части для заданного имени части связи.

Сравнение URI для эквивалентности

Приложению, использующим кэш для хранения частей при создании или использовании пакета, может потребоваться выполнить проверку эквивалентных имен частей. Метод PackUriHelper.ComparePartUri проверяет эквивалентность имен частей.

Пример: PackUriHelper.ComparePartUri

//Given two part names in the same package
//firstPartName = "/a.xaml"
//secondPartName = "/A.xaml"

//Use PackUriHelper.ComparePartUri to identify if the names 
//are equivalent.

Bool isSamePartName = PackUriHelper.ComparePartUri 
               (firstPartName, secondPartName);

//The resulting isSamePartName value is "TRUE"

Чтобы определить лексическую эквивалентность двух URI "pack:", используйте метод PackUriHelper.ComparePackUri .

Пример: PackUriHelper.ComparePackUri

//Given two "pack:" URIs
//firstPackUri =
// "PACK://HTTP%3A,,WWW.NEWSDOCS.COM,local,today.container
// /FILES/FIXEDDOC.XAML"
//secondPackUri = 
// "pack://http%3a,,www.newsdocs.com,local,today.container
// /files/fixeddoc.xaml"

//Use PackUriHelper.ComparePackUri to identify if the same resource 
//is targeted.

bool isSameResource = PackUriHelper.ComparePackUri 
            (firstPackUri, secondPackUri);

//The resulting isSameResource value is "TRUE"

Извлечение URI компонентов из универсального кода ресурса (URI) pack:

Чтобы извлечь URI пакета компонента и URI части из URI "pack:", используйте методы PackUriHelper.GetPackageUri и PackUriHelper.GetPartUri соответственно.

Пример: PackUriHelper.GetPackageUri

//Given the "pack:" URI for a package

Uri packUri = "pack://http%3a,,www.newsdocs.com,local,today.container
            /files/abc.xaml";

//Use PackUriHelper.GetPackageUri to obtain the URI of the package

Uri packageUri = new PackUriHelper.GetPackageUri(packUri);

//The resulting packageUri value is
//"http://www.newsdocs.com/local/today.container"

Пример. Пример GetPartUri

//Given the "pack:" URI for a part

Uri packUri = "pack://http%3a,,www.newsdocs.com,local,today.container
         /files/abc.xaml";

//Use PackUriHelper.GetPartUri to obtain the URI of the part

Uri partUri = new PackUriHelper.GetPartUri(packUri);

//The resulting partUri value is "/files/abc.xaml"

Ссылки

спецификации Open Packaging Conventions

Универсальный код ресурса (URI): общий синтаксис

OpenXPS

Международные идентификаторы ресурсов (IRIs)