📜 ⬆️ ⬇️

Serialization of static objects in C #

Context

I met this question while working on one of the projects, in which there are a lot of settings. Since the addition of new settings took place in the course of development, the need to make a class that can be accessed from any program module emerged. For this, of course, a static class was used, and we called it AppSettings. Of course, you could use Properties.Settings ... I will not go into details, but this option did not fit.

The essence of the problem
')
Because the class is static, normal serialization does not work. Let's check. Suppose we have a simple static class:
public static class TestStatic { // Fields... private static int _Counter; public static int Counter { get { return _Counter; } set { _Counter = value; } } } 


In general, if the class were not static, the System.Xml.Serialization.XmlSerializer could be used. This is not our case - the class is static and in this case, because the XmlSerializer.Serialize method requires an instance of the class, and not the type of the class, the compiler will give 'Test1.TestStatic' is a 'type' but is used like a ' variable '.

Decision

Googling a bit, did not find anything intelligible. The only thing I saw was how to classify a class that has static fields. In the brain spinning only Reflection. Well, after some experiments, I did the following class:

 public static class SerializeStatic { public static bool Save(Type static_class, string filename) { try { FieldInfo[] fields = static_class.GetFields(BindingFlags.Static | BindingFlags.NonPublic); object[,] a = new object[fields.Length, 2]; int i = 0; foreach (FieldInfo field in fields) { a[i, 0] = field.Name; a[i, 1] = field.GetValue(null); i++; }; Stream f = File.Open(filename, FileMode.Create); SoapFormatter formatter = new SoapFormatter(); formatter.Serialize(f, a); f.Close(); return true; } catch { return false; } } public static bool Load(Type static_class, string filename) { try { FieldInfo[] fields = static_class.GetFields(BindingFlags.Static | BindingFlags.NonPublic); object[,] a; Stream f = File.Open(filename, FileMode.Open); SoapFormatter formatter = new SoapFormatter(); a = formatter.Deserialize(f) as object[,]; f.Close(); if (a.GetLength(0) != fields.Length) return false; int i = 0; foreach (FieldInfo field in fields) { if (field.Name == (a[i, 0] as string)) { if (a[i, 1] != null) field.SetValue(null, a[i, 1]); } i++; }; return true; } catch { return false; } } } 


The point is simple:
  1. We receive static fields:
    FieldInfo [] fields = static_class.GetFields (BindingFlags.Static | BindingFlags.NonPublic);
  2. Create a matrix and drive the field name and value into it
  3. Well and then through SoapFormater we write to the file.


Loading from file is also performed. The only thing that in my opinion is worth noting: If in our class there is another class in one of the fields, then in this case it will suffice to designate the second class as [Serializable]. That is, if we have such an ad in TestStati:

 public static BrowserSettings OperaSettings { get { return _OperaSettings; } set { _OperaSettings = value; } } 

Then the BrowserSettings class will look something like this:
 [Serializable] public class BrowserSettings { //... } 


How to use

To save use:
 SerializeStatic.Save(typeof(TestStatic), "file.xml"); 


For loading:
 if (!SerializeStatic.Load(typeof(AppSettings), "file.xml")) ; 

Source: https://habr.com/ru/post/137405/


All Articles