Страницы

Поиск по вопросам

вторник, 28 января 2020 г.

Сериализация: как сохранить лист объектов своего класса в файл?

#c_sharp #settings #list #сериализация


Точнее говоря, вопрос в том, как сделать это:

Быстро;
Несколькими удобными строчками кода;
Туда и обратно, т.е. сохранять и загружать при запуске приложения;

Желательно сохранять всё это в settings (короче говоря, объекты из листов будут потом
загружаться в контролы, редактироваться из них, и после сохраняться). Проблема только
лишь в том, как их быстро и правильно сохранить.    


Ответы

Ответ 1



Я делал сериализацию в Xml так: public class MyClass { [XmlElement("Name")] public string Name {get; set;} // Это будет элементом [XmlAttribute("Value")] public string Value {get; set;} // Это будет атрибутом [XmlIgnore] public string ServiceField {get; set;} // Это поле мы не хотим сериализовать/десериализовать } public class MyClassCollection { [XmlArray("Collection"), XmlArrayItem("Item")] public List Collection {get; set;} } Затем сериализуем: XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyClassCollection)); StringWriter stringWriter = new StringWriter(); xmlSerializer.Serialize(stringWriter, myClassCollection); // myClassCollection - наши данные После чего получаем xml в виде строки из потока: string xml = stringWriter.ToString(); И десериализуем: var xmlSerializer = new XmlSerializer(typeof (MyClassCollection)); var stringReader = new StringReader(serializedData); MyClassCollection collection = (MyClassCollection) xmlSerializer.Deserialize(stringReader); Небольшие уточнения: Поля для сериализация обязательно должны быть с модификатором public Если Ваше поле имеет простой тип (например string) и Вы хотите его сделать XmlElement'ом, то расставлять атрибуты XmlElement не обязательно, поэтому иногда достаточно расставить XmlIgnore на тех свойсвтах, которые нам не нужны в сериализации/десериализации XmlSerializer может иногда бросать исключение FileNotFoundException и это считается нормальным его поведением, так что просто игнорируйте его. Вот ссылка, на SO, по этому поводу. Надеюсь поможет.

Ответ 2



Проще всего воспользоваться встроенным классом Settings. Единственная тонкость — нужен небольшой хак, чтобы поместить туда список. Вот код: using System; using System.Collections.Generic; using System.Linq; using SettingsTest.Properties; namespace SettingsTest { class Program { static void Main(string[] args) { new Program().RunData(); } List DataValues; void RunData() { // read DataValues = Settings.Default.DataValues; Console.WriteLine("Stored values:"); if (DataValues != null) { foreach (var d in DataValues) Console.WriteLine(d); } // modify Console.Write("Input int values separated by space: "); var input = Console.ReadLine(); DataValues = input.Split() .Select(int.Parse) .Select(i => new Data() { X = i, L = new List() { i - 1, i + 1 } }) .ToList(); // write back Settings.Default.DataValues = DataValues; Settings.Default.Save(); } } [Serializable] public class Data { public int X { get; set; } public List L { get; set; } public override string ToString() { return string.Format("Data(X = {0}, L = <{1}>)", X, string.Join(", ", L)); } } } Для того, чтобы поместить список в Settings, сделайте так: Откройте свойства проекта Перейдите во вкладку Settings. Если в вашем проекте ещё на добавлены Settings, добавьте их. Добавьте свойство с нужным именем (DataValues). Вы не сможете выбрать нужный тип (List), поэтому выберите, например, string. Зайдите в каталог проекта, и найдите там файл Properties\Settings.settings. Откройте его в редакторе, найдите строку

Ответ 3



Ответы прекрасные, плюсую оба, но ребят, девушка во первых просила удобный и быстрый способ. Но результатом вашей подсказки будет несколько классов содержащих свой сериализатор и громоздкий не масштабируемый код. Почему бы не показать сразу красивый вариант с внешним сериализатором, то биш просто вынести его в Extension, например так: public static class SerializeExtension { public static string SerializeToString(this object obj) { var xmlSerializer = new XmlSerializer(obj.GetType()); var stringWriter = new StringWriter(); xmlSerializer.Serialize(stringWriter, obj); return stringWriter.ToString(); } public static T DeserializeString(this string sourceString) { var xmlSerializer = new XmlSerializer(typeof(T)); var stringReader = new StringReader(sourceString); return (T)xmlSerializer.Deserialize(stringReader); } } и вот код xUnit теста для проверки результата: [Fact] public void FirstTest() { var myClass = new MyClassCollection { Collection = new List { new MyClass {Name = "name1", Value = "val1", ServiceField = "bla bla"}, new MyClass {Name = "name2", Value = "val2", ServiceField = "bla bla"}, new MyClass {Name = "name3", Value = "val3", ServiceField = "bla bla"}, new MyClass {Name = "name4", Value = "val4", ServiceField = "bla bla"} } }; var str = myClass.SerializeToString(); Console.WriteLine(str); var res = str.DeserializeString(); Assert.Equal(res.Collection[0].Name, "name1"); Assert.Equal(res.Collection[1].Name, "name2"); Assert.Equal(res.Collection[2].Name, "name3"); Assert.Equal(res.Collection[3].Name, "name4"); Assert.Equal(res.Collection[0].Value, "val1"); Assert.Equal(res.Collection[1].Value, "val2"); Assert.Equal(res.Collection[2].Value, "val3"); Assert.Equal(res.Collection[3].Value, "val4"); }

Ответ 4



[Serializable] class Program { static void Main(string[] args) { Serialize(); Deserialize(); } static void Serialize() { //создаем объект который будет сериализован List words = new List(); words.Add("мир"); words.Add("дверь"); words.Add("мяч"); //откроем поток для записи в файл FileStream fs = new FileStream("file.s", FileMode.Create, FileAccess.Write, FileShare.ReadWrite); BinaryFormatter bf = new BinaryFormatter(); //сериализация bf.Serialize(fs, words); fs.Close(); } static void Deserialize() { List words; FileStream fs = new FileStream("file.s", FileMode.Open, FileAccess.Read, FileShare.Read); BinaryFormatter bf=new BinaryFormatter(); words = (List)bf.Deserialize(fs); fs.Close(); foreach (string w in words) { Console.WriteLine(w); } } } Взято отсюда

Комментариев нет:

Отправить комментарий