Управление доставкой динамического содержимого в Silverlight - Политики срока действия

ОГЛАВЛЕНИЕ

Политики срока действия

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

Давайте посмотрим, что потребуется для добавления простой политики срока действия, которая по истечении указанного промежутка времени после загрузки выводит кэшированный файл XAP из употребления. Подходящим местом для настройки политики сроков действия является класс DownloadCache, такой как на рис. 6. При добавлении в кэш файла XAP необходимо сохранить некоторые сведения о моменте загрузки. При попытке получить доступ к кэшу для выбора пакета необходимо проверить срок действия пакета (см. рис. 9).

Рис. 9 Проверка срока действия

public bool IsExpired(string xapFile)
{
   bool expired = true;
   if (m_ItemsIndex.ContainsKey(xapFile))
   {
     DateTime dt = (DateTime)m_ItemsIndex[xapFile];

     // Expires after 1 hour
     expired = dt.AddSeconds(3600) < DateTime.Now;   
     if (expired)
       Remove(xapFile);
   }

   return expired;
}

Реализация такого очевидного алгоритма затруднена одним примечательным фактом. В Silverlight у вас нет никакого способа получения доступа к таким атрибутам файла, как время последнего обновления или время создания. Это означает, что за работу с информацией о времени отвечаете вы сами. Другими словами, при добавлении в кэш пакета XAP вы создаете также запись в некотором пользовательском постоянном словаре, отслеживающем момент загрузки пакета. Излишне говорить, что эту информацию необходимо некоторым способом сохранить в изолированном хранилище. Эта идея проиллюстрирована на рис. 10.

Рис. 10 Сохранение сведений о загрузке в изолированном хранилище

public static Stream Load(string file)
{
   IsolatedStorageFile iso;
   iso = IsolatedStorageFile.GetUserStoreForApplication();

   if (!iso.FileExists(file))
   {
     iso.Dispose();
     return null;
   }

   // Check some expiration policy
   CacheIndex m_Index = new CacheIndex();
   if (!m_Index.IsExpired(file))
     return iso.OpenFile(file, FileMode.Open);

   // Force reload
   iso.Dispose();
   return null;
}

CacheIndex является вспомогательным классом, который использует встроенный в Silverlight API настроек приложения для сохранения словаря имен XAP и моментов времени загрузки в изолированном хранилище. Член m_ItemIndex является простым объектом Dictionary, созданным в конструкторе CacheIndex, как показано на рис. 11.

Рис. 11. Класс CacheIndex

public class CacheIndex
{
   private const string XAPCACHENAME = "XapCache";
   private Dictionary<string, object> m_ItemsIndex; 
   public CacheIndex()
   {
    IsolatedStorageSettings iss;
    iss = IsolatedStorageSettings.ApplicationSettings;
    if (iss.Contains(XAPCACHENAME))
     m_ItemsIndex = iss[XAPCACHENAME] as Dictionary<string, object>;
    else
    {
     m_ItemsIndex = new Dictionary<string, object>();
     iss[XAPCACHENAME] = m_ItemsIndex;
     iss.Save();
    }
  }
  ...
}

ApplicationSettings является очень удобным средством Silverlight 2. Оно состоит из словаря строк/объектов, автоматически считывается из хранилища при загрузке приложения и сохраняется обратно в хранилище после завершения работы. Любой (сериализуемый) объект, добавляемый в словарь, сохраняется автоматически.

Создавая в словаре запись XAPCACHENAME, вы реорганизуете содержимое словаря XAP. В словаре XAP для каждого загруженного пакета содержится одна запись о времени загрузки, как видно из рис. 12. Отмечу, что API для ApplicationSettings предоставляет также метод Save для принудительного сохранения перед завершением работы приложения.

Рисунок 12 Добавление сведений о загрузке

public void Add(string xapFile)
{
   m_ItemsIndex[xapFile] = DateTime.Now;
   IsolatedStorageSettings iss;
   iss = IsolatedStorageSettings.ApplicationSettings;
   iss.Save();         
}

public void Remove(string xapFile)
{
   m_ItemsIndex.Remove(xapFile);
   IsolatedStorageSettings iss;
   iss = IsolatedStorageSettings.ApplicationSettings;
   iss.Save();
}