Postupy: Ukládání časových pásem do integrovaného prostředku

Aplikace pracující s časovým pásmem často vyžaduje přítomnost určitého časového pásma. Vzhledem k tomu, že dostupnost jednotlivých TimeZoneInfo objektů závisí na informacích uložených v registru místního systému, mohou chybět i vlastní dostupná časová pásma. Kromě toho se informace o vlastních časových pásmech vytvořených pomocí CreateCustomTimeZone metody neukládají s jinými informacemi o časovém pásmu v registru. Abyste zajistili, že jsou tato časová pásma dostupná v případě potřeby, můžete je uložit jejich serializací a později je obnovit deserializací.

Serializace objektu TimeZoneInfo se obvykle vyskytuje kromě aplikace pracující s časovým pásmem. V závislosti na úložišti dat používaném k uložení serializovaných TimeZoneInfo objektů mohou být data časového pásma serializována jako součást instalační nebo instalační rutiny (například když jsou data uložena v klíči aplikace registru) nebo jako součást rutiny nástroje, která se spouští před kompilací konečné aplikace (například při uložení serializovaných dat do souboru prostředku .NET XML (.resx).

Kromě souboru prostředků, který je kompilován s aplikací, lze pro informace o časovém pásmu použít několik dalších úložišť dat. Patří mezi ně následující:

  • Registr. Aplikace by měla použít podklíče vlastního klíče aplikace k ukládání vlastních dat časového pásma místo použití podklíčů HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\systém Windows NT\CurrentVersion\Time Zones.

  • Konfigurační soubory.

  • Jiné systémové soubory.

Uložení časového pásma serializací do souboru .resx

  1. Načtení existujícího časového pásma nebo vytvoření nového časového pásma

    Pokud chcete načíst existující časové pásmo, přečtěte si téma Postupy: Přístup k předdefinovaným objektům UTC a místním časovým pásmům a postupy: Vytvoření instance objektu TimeZoneInfo.

    Chcete-li vytvořit nové časové pásmo, zavolejte jedno z přetížení CreateCustomTimeZone metody. Další informace naleznete v tématu Postupy: Vytváření časových pásem bez pravidel úprav a Postupy: Vytváření časových pásem s pravidly úprav.

  2. ToSerializedString Voláním metody vytvořte řetězec, který obsahuje data časového pásma.

  3. StreamWriter Vytvořte instanci objektu zadáním názvu a volitelně cesty souboru .resx do konstruktoru StreamWriter třídy.

  4. ResXResourceWriter Vytvořte instanci objektu předáním StreamWriter objektu konstruktoru ResXResourceWriter třídy.

  5. Předejte serializovaný řetězec časového pásma metodě ResXResourceWriter.AddResource .

  6. Zavolejte metodu ResXResourceWriter.Generate .

  7. Zavolejte metodu ResXResourceWriter.Close .

  8. Zavřete StreamWriter objekt voláním jeho Close metody.

  9. Přidejte vygenerovaný soubor .resx do projektu sady Visual Studio aplikace.

  10. Pomocí okna Vlastnosti v sadě Visual Studio se ujistěte, že vlastnost Akce sestavení souboru .resx je nastavena na Vložený prostředek.

Příklad

Následující příklad serializuje TimeZoneInfo objekt, který představuje centrální standardní čas a TimeZoneInfo objekt, který představuje Palmer Station, Antarktida čas do souboru prostředků .NET XML s názvem SerializedTimeZones.resx. Centrální standardní čas je obvykle definován v registru; Palmer Station, Antarktida je vlastní časové pásmo.

TimeZoneSerialization()
{
   TextWriter writeStream;
   Dictionary<string, string> resources = new Dictionary<string, string>();
   // Determine if .resx file exists
   if (File.Exists(resxName))
   {
      // Open reader
      TextReader readStream = new StreamReader(resxName);
      ResXResourceReader resReader = new ResXResourceReader(readStream);
      foreach (DictionaryEntry item in resReader)
      {
         if (! (((string) item.Key) == "CentralStandardTime" ||
                ((string) item.Key) == "PalmerStandardTime" ))
            resources.Add((string)item.Key, (string) item.Value);
      }
      readStream.Close();
      // Delete file, since write method creates duplicate xml headers
      File.Delete(resxName);
   }

   // Open stream to write to .resx file
   try
   {
      writeStream = new StreamWriter(resxName, true);
   }
   catch (FileNotFoundException e)
   {
      // Handle failure to find file
      Console.WriteLine("{0}: The file {1} could not be found.", e.GetType().Name, resxName);
      return;
   }

   // Get resource writer
   ResXResourceWriter resWriter = new ResXResourceWriter(writeStream);

   // Add resources from existing file
   foreach (KeyValuePair<string, string> item in resources)
   {
      resWriter.AddResource(item.Key, item.Value);
   }

   // Serialize Central Standard Time
   try
   {
      TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
      resWriter.AddResource(cst.Id.Replace(" ", string.Empty), cst.ToSerializedString());
   }
   catch (TimeZoneNotFoundException)
   {
      Console.WriteLine("The Central Standard Time zone could not be found.");
   }

   // Create time zone for Palmer, Antarctica
   //
   // Define transition times to/from DST
   TimeZoneInfo.TransitionTime startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 4, 0, 0),
                                                                                              10, 2, DayOfWeek.Sunday);
   TimeZoneInfo.TransitionTime endTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0),
                                                                                            3, 2, DayOfWeek.Sunday);
   // Define adjustment rule
   TimeSpan delta = new TimeSpan(1, 0, 0);
   TimeZoneInfo.AdjustmentRule adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1999, 10, 1),
                                         DateTime.MaxValue.Date, delta, startTransition, endTransition);
   // Create array for adjustment rules
   TimeZoneInfo.AdjustmentRule[] adjustments = {adjustment};
   // Define other custom time zone arguments
   string DisplayName = "(GMT-04:00) Antarctica/Palmer Time";
   string standardName = "Palmer Standard Time";
   string daylightName = "Palmer Daylight Time";
   TimeSpan offset = new TimeSpan(-4, 0, 0);
   TimeZoneInfo palmer = TimeZoneInfo.CreateCustomTimeZone(standardName, offset, DisplayName, standardName, daylightName, adjustments);
   resWriter.AddResource(palmer.Id.Replace(" ", String.Empty), palmer.ToSerializedString());

   // Save changes to .resx file
   resWriter.Generate();
   resWriter.Close();
   writeStream.Close();
}
Private Sub SerializeTimeZones()
    Dim writeStream As TextWriter
    Dim resources As New Dictionary(Of String, String)
    ' Determine if .resx file exists
    If File.Exists(resxName) Then
        ' Open reader
        Dim readStream As TextReader = New StreamReader(resxName)
        Dim resReader As New ResXResourceReader(readStream)
        For Each item As DictionaryEntry In resReader
            If Not (CStr(item.Key) = "CentralStandardTime" Or _
                    CStr(item.Key) = "PalmerStandardTime") Then
                resources.Add(CStr(item.Key), CStr(item.Value))
            End If
        Next
        readStream.Close()
        ' Delete file, since write method creates duplicate xml headers
        File.Delete(resxName)
    End If

    ' Open stream to write to .resx file
    Try
        writeStream = New StreamWriter(resxName, True)
    Catch e As FileNotFoundException
        ' Handle failure to find file
        Console.WriteLine("{0}: The file {1} could not be found.", e.GetType().Name, resxName)
        Exit Sub
    End Try

    ' Get resource writer
    Dim resWriter As ResXResourceWriter = New ResXResourceWriter(writeStream)

    ' Add resources from existing file
    For Each item As KeyValuePair(Of String, String) In resources
        resWriter.AddResource(item.Key, item.Value)
    Next
    ' Serialize Central Standard Time
    Try
        Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
        resWriter.AddResource(cst.Id.Replace(" ", String.Empty), cst.ToSerializedString())
    Catch
        Console.WriteLine("The Central Standard Time zone could not be found.")
    End Try

    ' Create time zone for Palmer, Antarctica
    '
    ' Define transition times to/from DST
    Dim startTransition As TimeZoneInfo.TransitionTime = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#4:00:00 AM#, 10, 2, DayOfWeek.Sunday)
    Dim endTransition As TimeZoneInfo.TransitionTime = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#3:00:00 AM#, 3, 2, DayOfWeek.Sunday)
    ' Define adjustment rule
    Dim delta As TimeSpan = New TimeSpan(1, 0, 0)
    Dim adjustment As TimeZoneInfo.AdjustmentRule = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#10/1/1999#, Date.MaxValue.Date, delta, startTransition, endTransition)
    ' Create array for adjustment rules
    Dim adjustments() As TimeZoneInfo.AdjustmentRule = {adjustment}
    ' Define other custom time zone arguments
    Dim DisplayName As String = "(GMT-04:00) Antarctica/Palmer Time"
    Dim standardName As String = "Palmer Standard Time"
    Dim daylightName As String = "Palmer Daylight Time"
    Dim offset As TimeSpan = New TimeSpan(-4, 0, 0)
    Dim palmer As TimeZoneInfo = TimeZoneInfo.CreateCustomTimeZone(standardName, offset, DisplayName, standardName, daylightName, adjustments)
    resWriter.AddResource(palmer.Id.Replace(" ", String.Empty), palmer.ToSerializedString())

    ' Save changes to .resx file 
    resWriter.Generate()
    resWriter.Close()
    writeStream.Close()
End Sub

Tento příklad serializuje TimeZoneInfo objekty tak, aby byly k dispozici v souboru prostředků v době kompilace.

Vzhledem k tomu, že ResXResourceWriter.Generate metoda přidá úplné informace hlavičky do souboru prostředků .NET XML, nelze jej použít k přidání prostředků do existujícího souboru. Příklad to zpracuje tak, že vyhledá soubor SerializedTimeZones.resx a pokud existuje, uloží všechny jeho prostředky kromě dvou serializovaných časových pásem do obecného Dictionary<TKey,TValue> objektu. Existující soubor se pak odstraní a existující prostředky se přidají do nového souboru SerializedTimeZones.resx. Do tohoto souboru se také přidají serializovaná data časového pásma.

Pole klíče (nebo názvu) prostředků by neměla obsahovat vložené mezery. Metoda Replace(String, String) je volána k odebrání všech vložených mezer v identifikátorech časového pásma dříve, než jsou přiřazeny k souboru prostředků.

Zkompilování kódu

Tento příklad vyžaduje:

  • Odkaz na System.Windows.Forms.dll a System.Core.dll se do projektu přidá.

  • Importují se následující obory názvů:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Reflection;
    using System.Resources;
    using System.Windows.Forms;
    
    Imports System.Globalization
    Imports System.IO
    Imports System.Reflection
    Imports System.Resources
    

Viz také