Instrukcje: Zapisywanie stref czasowych w zasobie osadzonym

Aplikacja z obsługą stref czasowych często wymaga obecności określonej strefy czasowej. Jednak ze względu na to, że dostępność poszczególnych TimeZoneInfo obiektów zależy od informacji przechowywanych w rejestrze systemu lokalnego, nawet niestandardowe dostępne strefy czasowe mogą być nieobecne. Ponadto informacje o niestandardowych strefach czasowych utworzone za pomocą CreateCustomTimeZone metody nie są przechowywane z innymi informacjami o strefie czasowej w rejestrze. Aby upewnić się, że te strefy czasowe są dostępne w razie potrzeby, można je zapisać, serializując je, a następnie przywrócić je, deserializując je.

Zazwyczaj serializowanie TimeZoneInfo obiektu odbywa się niezależnie od aplikacji obsługującej strefy czasowej. W zależności od magazynu danych używanego do przechowywania serializowanych TimeZoneInfo obiektów dane strefy czasowej mogą być serializowane w ramach procedury instalacji lub instalacji (na przykład gdy dane są przechowywane w kluczu aplikacji rejestru) lub w ramach procedury narzędzi, która jest uruchamiana przed skompilowaną ostateczną aplikacją (na przykład gdy serializowane dane są przechowywane w pliku zasobu XML platformy .NET (resx).

Oprócz pliku zasobu skompilowanego z aplikacją można użyć kilku innych magazynów danych na potrzeby informacji o strefie czasowej. Należą do nich następujące funkcje:

  • Rejestr. Należy pamiętać, że aplikacja powinna używać podklucza własnego klucza aplikacji do przechowywania niestandardowych danych strefy czasowej, a nie używania podkluczów HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones.

  • Pliki konfiguracji.

  • Inne pliki systemowe.

Aby zapisać strefę czasową, serializując ją w pliku resx

  1. Pobierz istniejącą strefę czasową lub utwórz nową strefę czasową.

    Aby pobrać istniejącą strefę czasową, zobacz Instrukcje: uzyskiwanie dostępu do wstępnie zdefiniowanych obiektów strefy czasowej UTC i lokalnych oraz Instrukcje: tworzenie wystąpienia obiektu TimeZoneInfo.

    Aby utworzyć nową strefę czasową, wywołaj jedno z przeciążeń CreateCustomTimeZone metody . Aby uzyskać więcej informacji, zobacz How to: Create time zones without adjustment rules (Jak tworzyć strefy czasowe bez reguł korekt) i How to: Create time zones with adjustment rules (Jak tworzyć strefy czasowe z regułami korekt).

  2. Wywołaj metodę , ToSerializedString aby utworzyć ciąg zawierający dane strefy czasowej.

  3. StreamWriter Utwórz wystąpienie obiektu, podając nazwę i opcjonalnie ścieżkę pliku resx do konstruktora StreamWriter klasy.

  4. Utwórz wystąpienie ResXResourceWriter obiektu, przekazując StreamWriter obiekt do konstruktora ResXResourceWriter klasy.

  5. Przekaż ciąg serializowany strefy czasowej do ResXResourceWriter.AddResource metody .

  6. Wywołaj metodę ResXResourceWriter.Generate .

  7. Wywołaj metodę ResXResourceWriter.Close .

  8. StreamWriter Zamknij obiekt, wywołując jego Close metodę.

  9. Dodaj wygenerowany plik resx do projektu programu Visual Studio aplikacji.

  10. Korzystając z okna Właściwości w programie Visual Studio, upewnij się, że właściwość Akcja kompilacji pliku resx jest ustawiona na zasób osadzony.

Przykład

W poniższym przykładzie serializuje obiekt reprezentujący centralną TimeZoneInfo standardową TimeZoneInfo godzinę i obiekt reprezentujący czas Palmer Station, Antarktydy do pliku zasobów XML platformy .NET o nazwie SerializedTimeZones.resx. Środkowy czas standardowy jest zwykle definiowany w rejestrze; Palmer Station, Antarktyda jest niestandardową strefą czasową.

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

W tym przykładzie serializuje TimeZoneInfo obiekty, aby były dostępne w pliku zasobów w czasie kompilacji.

ResXResourceWriter.Generate Ponieważ metoda dodaje pełne informacje nagłówka do pliku zasobu XML platformy .NET, nie może służyć do dodawania zasobów do istniejącego pliku. Przykład obsługuje to, sprawdzając plik SerializedTimeZones.resx i, jeśli istnieje, przechowując wszystkie jego zasoby inne niż dwie serializowane strefy czasowe do obiektu ogólnego Dictionary<TKey,TValue> . Istniejący plik zostanie usunięty, a istniejące zasoby zostaną dodane do nowego pliku SerializedTimeZones.resx. Do tego pliku są również dodawane serializowane dane strefy czasowej.

Pola klucza (lub nazwy) zasobów nie powinny zawierać osadzonych spacji. Metoda jest wywoływana Replace(String, String) w celu usunięcia wszystkich osadzonych przestrzeni w identyfikatorach strefy czasowej, zanim zostaną przypisane do pliku zasobu.

Kompilowanie kodu

Ten przykład wymaga:

  • To odwołanie do System.Windows.Forms.dll i System.Core.dll należy dodać do projektu.

  • Aby zaimportować następujące przestrzenie nazw:

    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
    

Zobacz też