Delen via


Procedure: Tijdzones besparen op een ingesloten resource

Een tijdzonebewuste toepassing vereist vaak de aanwezigheid van een bepaalde tijdzone. Omdat de beschikbaarheid van afzonderlijke TimeZoneInfo objecten echter afhankelijk is van gegevens die zijn opgeslagen in het register van het lokale systeem, kunnen zelfs aangepaste beschikbare tijdzones afwezig zijn. Daarnaast wordt informatie over aangepaste tijdzones die met behulp van de CreateCustomTimeZone methode worden geïnstantieerd, niet opgeslagen met andere tijdzone-informatie in het register. Om ervoor te zorgen dat deze tijdzones beschikbaar zijn wanneer ze nodig zijn, kunt u ze opslaan door ze te serialiseren en ze later te herstellen door ze te deserialiseren.

Normaal gesproken treedt het serialiseren van een TimeZoneInfo object op, afgezien van de tijdzonebewuste toepassing. Afhankelijk van het gegevensarchief dat wordt gebruikt voor het opslaan van geserialiseerde TimeZoneInfo objecten, kunnen tijdzonegegevens worden geserialiseerd als onderdeel van een installatie- of installatieroutine (bijvoorbeeld wanneer de gegevens worden opgeslagen in een toepassingssleutel van het register) of als onderdeel van een hulpprogrammaroutine die wordt uitgevoerd voordat de uiteindelijke toepassing wordt gecompileerd (bijvoorbeeld wanneer de geserialiseerde gegevens worden opgeslagen in een .NET XML-resourcebestand (.resx).

Naast een resourcebestand dat met de toepassing is gecompileerd, kunnen verschillende andere gegevensarchieven worden gebruikt voor tijdzone-informatie. Dit zijn onder meer de volgende:

  • Het register. Houd er rekening mee dat een toepassing de subsleutels van zijn eigen toepassingssleutel moet gebruiken om aangepaste tijdzonegegevens op te slaan in plaats van de subsleutels van HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Tijdzones.

  • Configuratiebestanden.

  • Andere systeembestanden.

Een tijdzone opslaan door deze te serialiseren naar een RESX-bestand

  1. Haal een bestaande tijdzone op of maak een nieuwe tijdzone.

    Als u een bestaande tijdzone wilt ophalen, raadpleegt u: Toegang krijgen tot de vooraf gedefinieerde UTC- en lokale tijdzoneobjecten en procedures: een TimeZoneInfo-object instantiëren.

    Als u een nieuwe tijdzone wilt maken, roept u een van de overbelastingen van de CreateCustomTimeZone methode aan. Zie Voor meer informatie : Tijdzones maken zonder aanpassingsregels en procedures: Tijdzones maken met aanpassingsregels.

  2. Roep de ToSerializedString methode aan om een tekenreeks te maken die de gegevens van de tijdzone bevat.

  3. Instantieer een StreamWriter object door de naam en eventueel het pad van het RESX-bestand op te geven aan de StreamWriter klasseconstructor.

  4. Instantieer een ResXResourceWriter object door het StreamWriter object door te geven aan de ResXResourceWriter klasseconstructor.

  5. Geef de geserialiseerde tekenreeks van de tijdzone door aan de ResXResourceWriter.AddResource methode.

  6. Roep de ResXResourceWriter.Generate methode aan.

  7. Roep de ResXResourceWriter.Close methode aan.

  8. Sluit het object door de StreamWriter methode aan Close te roepen.

  9. Voeg het gegenereerde RESX-bestand toe aan het Visual Studio-project van de toepassing.

  10. Controleer in het venster Eigenschappen in Visual Studio of de eigenschap Build Action van het RESX-bestand is ingesteld op Ingesloten resource.

Opmerking

In het volgende voorbeeld wordt een TimeZoneInfo object geserialiseerd dat Central Standard Time vertegenwoordigt en een TimeZoneInfo object dat het Palmer Station vertegenwoordigt, Antarctica-tijd naar een .NET XML-resourcebestand met de naam SerializedTimeZones.resx. Central Standard Time wordt doorgaans gedefinieerd in het register; Palmer Station, Antarctica is een aangepaste tijdzone.

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

In dit voorbeeld worden objecten geserialiseerd zodat ze tijdens het compileren TimeZoneInfo beschikbaar zijn in een resourcebestand.

Omdat de ResXResourceWriter.Generate methode volledige headergegevens toevoegt aan een .NET XML-resourcebestand, kan deze niet worden gebruikt om resources toe te voegen aan een bestaand bestand. In het voorbeeld wordt dit afgehandeld door te controleren op het bestand SerializedTimeZones.resx en, als het bestaat, alle resources op te slaan die niet de twee geserialiseerde tijdzones naar een algemeen Dictionary<TKey,TValue> object zijn. Het bestaande bestand wordt vervolgens verwijderd en de bestaande resources worden toegevoegd aan een nieuw SerializedTimeZones.resx-bestand. De geserialiseerde tijdzonegegevens worden ook toegevoegd aan dit bestand.

De sleutelvelden (of naam) van resources mogen geen ingesloten spaties bevatten. De Replace(String, String) methode wordt aangeroepen om alle ingesloten spaties in de tijdzone-id's te verwijderen voordat ze worden toegewezen aan het resourcebestand.

De code compileren

Voor dit voorbeeld is het volgende vereist:

  • Dat een verwijzing naar System.Windows.Forms.dll en System.Core.dll aan het project worden toegevoegd.

  • De volgende naamruimten worden geïmporteerd:

    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
    

Zie ook