Dela via


Gör så här: Spara tidszoner i en inbäddad resurs

Ett tidszonsmedvetent program kräver ofta att det finns en viss tidszon. Men eftersom tillgängligheten för enskilda TimeZoneInfo objekt är beroende av information som lagras i det lokala systemets register, kan även vanligtvis tillgängliga tidszoner vara frånvarande. Dessutom lagras inte information om anpassade tidszoner som instansieras med hjälp CreateCustomTimeZone av metoden med annan tidszonsinformation i registret. För att säkerställa att dessa tidszoner är tillgängliga när de behövs kan du spara dem genom att serialisera dem och senare återställa dem genom att deserialisera dem.

Vanligtvis sker serialisering av ett TimeZoneInfo objekt förutom det tidszonsmedvetna programmet. Beroende på vilket datalager som används för att lagra serialiserade TimeZoneInfo objekt kan tidszonsdata serialiseras som en del av en konfigurations- eller installationsrutin (till exempel när data lagras i en programnyckel i registret) eller som en del av en verktygsrutin som körs innan det slutliga programmet kompileras (till exempel när serialiserade data lagras i en .NET XML-resursfil (.resx).

Förutom en resursfil som kompileras med programmet kan flera andra datalager användas för tidszonsinformation. Dessa omfattar följande:

  • Registret. Observera att ett program bör använda undernycklarna för sin egen programnyckel för att lagra anpassade tidszonsdata i stället för att använda undernycklarna för HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Tidszoner.

  • Konfigurationsfiler.

  • Andra systemfiler.

Spara en tidszon genom att serialisera den till en .resx-fil

  1. Hämta en befintlig tidszon eller skapa en ny tidszon.

    Information om hur du hämtar en befintlig tidszon finns i How to: Access the predefined UTC and local time zone objects and How to: Instansiera ett TimeZoneInfo-objekt.

    Om du vill skapa en ny tidszon anropar du en av överlagringarna av CreateCustomTimeZone metoden. Mer information finns i Så här skapar du tidszoner utan justeringsregler och Så här skapar du tidszoner med justeringsregler.

  2. ToSerializedString Anropa metoden för att skapa en sträng som innehåller tidszonens data.

  3. Instansiera ett StreamWriter objekt genom att ange namnet och eventuellt sökvägen till .resx-filen till StreamWriter klasskonstruktorn.

  4. Instansiera ett ResXResourceWriter objekt genom att skicka objektet StreamWriter till ResXResourceWriter klasskonstruktorn.

  5. Skicka tidszonens serialiserade sträng till ResXResourceWriter.AddResource metoden.

  6. ResXResourceWriter.Generate Anropa metoden.

  7. ResXResourceWriter.Close Anropa metoden.

  8. Stäng objektet StreamWriter genom att anropa dess Close metod.

  9. Lägg till den genererade .resx-filen i programmets Visual Studio-projekt.

  10. Använd fönstret Egenskaper i Visual Studio och kontrollera att .resx-filens build action-egenskap är inställd på Inbäddad resurs.

Exempel

I följande exempel serialiseras ett TimeZoneInfo objekt som representerar central standardtid och ett TimeZoneInfo objekt som representerar Palmer Station, Antarktistid till en .NET XML-resursfil med namnet SerializedTimeZones.resx. Central standardtid definieras vanligtvis i registret. Palmer Station, Antarktis är en anpassad tidszon.

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

Det här exemplet serialiserar TimeZoneInfo objekt så att de är tillgängliga i en resursfil vid kompileringstillfället.

ResXResourceWriter.Generate Eftersom metoden lägger till fullständig rubrikinformation i en .NET XML-resursfil kan den inte användas för att lägga till resurser i en befintlig fil. Exemplet hanterar detta genom att söka efter filen SerializedTimeZones.resx och, om den finns, lagra alla dess resurser förutom de två serialiserade tidszonerna till ett allmänt Dictionary<TKey,TValue> objekt. Den befintliga filen tas sedan bort och de befintliga resurserna läggs till i en ny SerializedTimeZones.resx-fil. Serialiserade tidszonsdata läggs också till i den här filen.

Nyckelfälten (eller Namn) för resurser får inte innehålla inbäddade blanksteg. Metoden Replace(String, String) anropas för att ta bort alla inbäddade blanksteg i tidszonsidentifierarna innan de tilldelas till resursfilen.

Kompilera koden

Det här exemplet kräver:

  • Att en referens till System.Windows.Forms.dll och System.Core.dll läggas till i projektet.

  • Att följande namnområden importeras:

    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
    

Se även