Feedback

C# - Fast & Easy to use serializable Settings-Class

Veröffentlicht von am 11/17/2009
(2 Bewertungen)
Ich bin ein notorisch fauler Mensch, und wenn es eins gibt, was ich nicht ab kann, dann ist das Fleißarbeit bei der Programmierung.

Wer ab und zu mal was serialisieren muss, der kennt bestimmt den Deserialization Constructor und die Serialization Funktion GetObjectData().

Im normalfall müssen der Constructor und die Funktion aufwändig mit allen Properties/Fields gefüllt werden, die serialisiert werden sollen.

Beispiel:

// Deserialization Constructor
public Settings(SerializationInfo info, StreamingContext ctxt)
{
//Get the values from info and assign them to the appropriate properties

DatabaseServer = (string)info.GetValue("DatabaseServer", typeof(string));
DatabaseServerDatabase = (string)info.GetValue("DatabaseServerDatabase", typeof(string));
DatabaseServerUser = (string)info.GetValue("DatabaseServerUser", typeof(string));
DatabaseServerPassword = (string)info.GetValue("DatabaseServerPassword", typeof(string));

WindowMaximized = (bool)info.GetValue("WindowMaximized", typeof(bool));

WindowLeft = (int)info.GetValue("WindowLeft", typeof(int));
WindowTop = (int)info.GetValue("WindowTop", typeof(int));
WindowWidth = (int)info.GetValue("WindowWidth", typeof(int));
WindowHeight = (int)info.GetValue("WindowHeight", typeof(int));
}

// Serialization function
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
info.AddValue("DatabaseServer", DatabaseServer);
info.AddValue("DatabaseServerDatabase", DatabaseServerDatabase);
info.AddValue("DatabaseServerUser", DatabaseServerUser);
info.AddValue("DatabaseServerPassword", DatabaseServerPassword);

info.AddValue("WindowMaximized", WindowMaximized);

info.AddValue("WindowLeft", WindowLeft);
info.AddValue("WindowTop", WindowTop);
info.AddValue("WindowWidth", WindowWidth);
info.AddValue("WindowHeight", WindowHeight);
}


Das kann bei einer größeren Anzahl von Properties schnell zu Arbeit ausarten und genau hier kommt meine Settings-Hilfsklasse ins Spiel, schaut euch mal die Funktionen 'GetPropertiesFromObject' und 'SetPropertiesToObject' an, in denen laufe ich einfach über alle Properties (könnten auch die Fields sein) und de- oder serialisiere diese.

Und mit den Funktionen 'ReadFromFile' und 'WriteToFile' habt Ihr dann auch gleich die passenden Mittel um die serialisierten Daten in eine Datei zu schreiben und diese wieder einzulesen.

Da es sich um eine 'Hilfsklasse' handelt, stehen nichts in der Properties-Region und im Settings-Constructor (Init)
Ich leite von der Klasse ab, lege den Deserialization-Constructor - und die Properties die ich brauche an, und rufe an passender Stelle die Read- und Write-Funktionen auf (z.B. bei einer Form im Load-Event und im FormClosing-Event).

Beispiel:

using System;
using System.Runtime.Serialization;
using CKing.UniversalLibrary.Helpers;

namespace CKing.TestApp
{
[Serializable()]
public class TestSettings : Settings
{
#region Properties

public string DatabaseServer { get; set; }
public string DatabaseServerDatabase { get; set; }
public string DatabaseServerUser { get; set; }
public string DatabaseServerPassword { get; set; }

public bool WindowMaximized { get; set; }

public int WindowLeft { get; set; }
public int WindowTop { get; set; }
public int WindowWidth { get; set; }
public int WindowHeight { get; set; }

#endregion Properties

#region Constructor

public TestSettings()
{
this.DatabaseServer = string.Empty;
this.DatabaseServerDatabase = string.Empty;
this.DatabaseServerUser = string.Empty;
this.DatabaseServerPassword = string.Empty;

this.WindowMaximized = false;

this.WindowLeft = 0;
this.WindowTop = 0;
this.WindowWidth = 666;
this.WindowHeight = 444;
}

#region Serialization Constructor

// Deserialization Constructor
public TestSettings(SerializationInfo info, StreamingContext ctxt) : base(info, ctxt)
{
}

#endregion Serialization Constructor

#endregion Constructor
}
}


So ich hoffe ich habe nicht zuviel blödsinn geschrieben, wenn ich irgendwas vergessen habe, oder Fehler enthalten sind, dann meldet euch.

Gruß,
Chriss
using System;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace CKing.UniversalLibrary.Helpers
{
  [Serializable()]
  public class Settings : ISerializable
  {
    #region Properties

    // Write your Properties here.
    ////////////////////////////////////////////////////////////////////

    // public string VarXYZ{ get; set; }

    #endregion Properties

    #region Constructor

    public Settings()
    {
      // And don't forget to set default values here.
      ////////////////////////////////////////////////////////////////////

      // this.VarXYZ = string.Empty;
    }

    #endregion Constructor

    #region Serialization

    /// <summary>
    /// Deserialization Constructor
    /// </summary>
    /// <param name="si"></param>
    /// <param name="sc"></param>
    public Settings(SerializationInfo si, StreamingContext sc)
    {
      this.SetPropertiesToObject(si, this);
    }

    /// <summary>
    /// Serialization Method
    /// </summary>
    /// <param name="si"></param>
    /// <param name="sc"></param>
    public void GetObjectData(SerializationInfo si, StreamingContext sc)
    {
      this.GetPropertiesFromObject(si, this);
    }

    private bool SetPropertiesToObject(SerializationInfo si, object obj)
    {
      try
      {
        if (obj == null)
          return false;

        MemberInfo[] miArray = obj.GetType().GetMembers();
        foreach (MemberInfo mi in miArray)
        {
          if (mi.MemberType == MemberTypes.Property)
          {
            PropertyInfo pi = (PropertyInfo)mi;

            string name = pi.Name;

            if (name == null && name.Length < 1)
              continue;

            try
            {
              if (pi.PropertyType.UnderlyingSystemType == typeof(string))
              {
                pi.SetValue(obj, (string)si.GetValue(name, typeof(string)), null);
              }
              else if (pi.PropertyType.UnderlyingSystemType == typeof(int))
              {
                pi.SetValue(obj, (int)si.GetValue(name, typeof(int)), null);
              }
              else if (pi.PropertyType.UnderlyingSystemType == typeof(bool))
              {
                pi.SetValue(obj, (bool)si.GetValue(name, typeof(bool)), null);
              }
              else
                continue;
            }
            catch
            {
              continue;
            }
          }
        }

        return true;
      }
      catch (Exception ex)
      {
        System.Diagnostics.Trace.Write(ex.ToString());

        return false;
      }
    }

    private bool GetPropertiesFromObject(SerializationInfo si, object obj)
    {
      try
      {
        if (obj == null)
          return false;

        MemberInfo[] miArray = obj.GetType().GetMembers();
        foreach (MemberInfo mi in miArray)
        {
          if (mi.MemberType == MemberTypes.Property)
          {
            PropertyInfo pi = (PropertyInfo)mi;

            string name = pi.Name;
            object value = pi.GetValue(obj, null);

            if (name != null && name.Length > 0 && value != null && value.ToString().Length > 0)
              si.AddValue(name, value, pi.PropertyType.UnderlyingSystemType);
          }
        }

        return true;
      }
      catch (Exception ex)
      {
        System.Diagnostics.Trace.Write(ex.ToString());

        return false;
      }
    }

    public static bool WriteToFile(string filename, object obj)
    {
      return Settings.BinarySerialize(filename, obj);
    }

    private static bool BinarySerialize(string filename, object obj)
    {
      try
      {
        DirectoryInfo di = new FileInfo(filename).Directory;
        if (obj != null && di != null && di.Exists)
        {
          using (FileStream fs = new FileStream(filename, FileMode.Create))
          {
            using (GZipStream zs = new GZipStream(fs, CompressionMode.Compress))
            {
              BinaryFormatter bf = new BinaryFormatter();
              bf.Serialize(zs, obj);
            }
          }
        }
        return true;
      }
      catch (Exception ex)
      {
        System.Diagnostics.Trace.Write(ex.ToString());

        return false;
      }
    }

    public static object ReadFromFile(string filename)
    {
      return Settings.BinaryDeserialize(filename);
    }

    private static object BinaryDeserialize(string filename)
    {
      try
      {
        FileInfo fi = new FileInfo(filename);
        if (fi == null || !fi.Exists)
          return null;

        using (FileStream fs = new FileStream(filename, FileMode.Open))
        {
          using (GZipStream zs = new GZipStream(fs, CompressionMode.Decompress))
          {
            BinaryFormatter bf = new BinaryFormatter();
            return bf.Deserialize(zs);
          }
        }
      }
      catch (Exception ex)
      {
        System.Diagnostics.Trace.Write(ex.ToString());

        return null;
      }
    }

    #endregion Serialization
  }
}

3 Kommentare zum Snippet

Christian Köwing schrieb am 11/17/2009:
Was ein Käse, kann man seine Snippets nicht editieren? Sorry, aber da ist was mit dem BB-Code [Code] schief gegangen.
Christopher Kk schrieb am 11/17/2009:
Doch du kannst es editieren. Rechts unten da wo auch der Grüne "Pfeil" und der "Drucker" ist, sollte auch ein "NotePad" Icon sein mit welchem dein Snippet editieren kannst.
Christian Köwing schrieb am 11/17/2009:
Vielen Dank Christopher.
 

Logge dich ein, um hier zu kommentieren!