Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.74/39: Рейтинг темы: голосов - 39, средняя оценка - 4.74
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
1
.NET 4.x

Сохранение списка объектов класса в ручную, сохранение в XML. Без сериализации.

26.12.2010, 01:45. Показов 7088. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте! Хотел спросить. Как можно сохранить список объектов в XML файл вручную? Я сериализацией делаю так:
Класс, который будем сохранять и класс, который сериализовывает список объектов класса.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
 
namespace TestProgram
{
    [Serializable]
    public enum Mode : byte
    {
        Single, Double, Decimal
    }
 
    [Serializable]
    public class TestObject
    {
        public int valueInt { get; set; }
        public String valueText { get; set; }
        public DateTime valueDateTime { get; set; }
        public Mode enumMode { get; set; }
 
        public TestObject()
        {
        }
 
        public TestObject(int valInt, String valText, DateTime valDateTime, Mode enumMode)
        {
            this.valueInt = valInt;
            this.valueText = valText;
            this.valueDateTime = valDateTime;
            this.enumMode = enumMode;
        }
    }
 
    public static class SaverLoader
    {
        public static void Save(List<TestObject> list, String FileName)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<TestObject>));
            TextWriter textWriter = new StreamWriter(FileName);
            xmlSerializer.Serialize(textWriter, list);
            textWriter.Close();
        }
 
        public static List<TestObject> Load(String FileName)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<TestObject>));
            TextReader textReader = new StreamReader(FileName);
            List<TestObject> list = (List<TestObject>)xmlSerializer.Deserialize(textReader);
            textReader.Close();
            return list;
        }
    }
}
Вот я создаю объекты, добавляю их в список и сохраняю сериализацией в XML:
C#
1
2
3
4
5
6
7
8
9
10
11
12
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            const int countObj = 3;
            List<TestObject> list = new List<TestObject>(countObj);
 
            Mode[] modes = new Mode[countObj] { Mode.Decimal, Mode.Double, Mode.Single };
 
            for (int i = 0; i < countObj; i++)
                list.Add(new TestObject(i, "Привет " + i.ToString(), new DateTime(2010, 12, i + 1), modes[i]));
            String path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "SaveFile.xml");
            SaverLoader.Save(list, path);
        }
И получаю файл следующего вида:
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfTestObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TestObject>
    <valueInt>0</valueInt>
    <valueText>Привет 0</valueText>
    <valueDateTime>2010-12-01T00:00:00</valueDateTime>
    <enumMode>Decimal</enumMode>
  </TestObject>
  <TestObject>
    <valueInt>1</valueInt>
    <valueText>Привет 1</valueText>
    <valueDateTime>2010-12-02T00:00:00</valueDateTime>
    <enumMode>Double</enumMode>
  </TestObject>
  <TestObject>
    <valueInt>2</valueInt>
    <valueText>Привет 2</valueText>
    <valueDateTime>2010-12-03T00:00:00</valueDateTime>
    <enumMode>Single</enumMode>
  </TestObject>
</ArrayOfTestObject>
Вот мне хотелось бы узнать как создать такой файл вручную, из списка? И как потом загрузить тоже в список. Я что-то вообще запутался. Особенно эта беда мне не совсем ясна, как сделать:
XML
1
2
3
<ArrayOfTestObject>
......
</ArrayOfTestObject>
Добавлено через 20 минут
Вообще, хотябы узнать, как загружать такого вида список. Мне нужно это, чтобы в новой версии программы конвертировать сохранённые настройки в новый изменённый класс... Ну и не только настройки, кое какие объекты ещё...
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.12.2010, 01:45
Ответы с готовыми решениями:

Сохранение объектов класса в Xml файл
нужно сохранить значение классов в xml файл описание одного из классов class AnimalTip { ...

Сохранение объектов в XML. Вложенность 3 порядка
Здравствуйте. Нужна помощь. Есть класс &quot;Проба&quot; public class Sample { public int...

Сохранение объектов класса в файл
Есть несколько массивов, которые создаются по ходу работы приложения, и которые нужно сохранять в...

Создание/сохранение класса из/в XML
Создание/сохранение класса из/в XML с какой стороны подойти какую литературу почитать

7
1513 / 780 / 103
Регистрация: 22.04.2008
Сообщений: 1,610
26.12.2010, 02:08 2
Можно использовать Linq to XML
Вот когда то написал класс repository который сохраняет список обектов можно добавлять удалять
класс который будет записан в Xml
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
using System.Collections.Generic;
 
namespace UserLogic
{
    [Serializable]
    public class ProjectLog
    {
        public string UserId { get; set; }
        public string ProjectId { get; set; }
        public TimeSpan DurationTime { get; set; }
        public DateTime StartDate { get; set; }
    }
    [Serializable]
    public class ProjectLogEntries:List<ProjectLog>
    {
        
    }
}
Сам класс для работы с данными в Xml
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using UserLogic.Domain;
 
namespace UserLogic
{
    public class ProjectLogXmlRepository:IProjectLogRepository
    {
        private const string ProjectEntry = "ProjectEntry";
        private readonly string fileName;
        private readonly XDocument xDocument;
 
 
        public ProjectLogXmlRepository(string fileName)
        {
            this.fileName = fileName;
            if (File.Exists(fileName))
            {
                xDocument = XDocument.Load(fileName);
            }
            else
            {
                xDocument = new XDocument();
                xDocument.Add(new XElement("ProjectsLog"));
            }
 
        }
 
        #region Implementation of IProjectLogRepository
 
        public void Add(ProjectLog projectLog)
        {
            var xElement = new XElement(ProjectEntry);
 
            xElement.Add(new XAttribute("UserId",projectLog.UserId));
            xElement.Add(new XAttribute("ProjectId", projectLog.ProjectId));
            xElement.Add(new XAttribute("DurationTime", projectLog.DurationTime.ToString()));
            xElement.Add(new XAttribute("StartDate", projectLog.StartDate));
 
            if (xDocument.Root != null) 
                xDocument.Root.Add(xElement);
            
        }
 
        public void Delete(ProjectLog projectLog)
        {
            if (xDocument.Root != null)
            {
                var project =
                    xDocument.Root.Descendants(ProjectEntry).Where(
                        element => (DateTime.Parse(element.Attribute("StartDate").Value) == projectLog.StartDate
                                   )).SingleOrDefault();
                if (project != null)
                {
                    project.Remove();
                }
               
            }
           
        }
 
        public void Save()
        {
            xDocument.Save(fileName);
           
        }
 
        public List<ProjectLog> GetProjects()
        {
            if (xDocument.Root != null)
            {
                var projects = from project in xDocument.Root.Descendants(ProjectEntry)
                               select new ProjectLog
                                          {
 
                                              ProjectId = project.Attribute("ProjectId").Value,
                                              UserId = project.Attribute("UserId").Value,
                                              DurationTime = TimeSpan.Parse(project.Attribute("DurationTime").Value),
                                              StartDate = DateTime.Parse(project.Attribute("StartDate").Value)
                                          };
                    
                return projects.ToList();
            }
            return new List<ProjectLog>();
 
        }
 
        #endregion
    }
}
интерфейс
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.Collections.Generic;
using UserLogic.Domain;
 
namespace UserLogic
{
    public interface IProjectLogRepository
    {
        void Add(ProjectLog projectLog);
        void Delete(ProjectLog projectLog);
        void Save();
        List<ProjectLog> GetProjects();
    }
 
   
}
2
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
26.12.2010, 02:10 3
бывает разные уровни "ручнистости"

1) перебрать список и сериализовать каждый элемент обычным XmlsSerializer
2) реализовать IXmlSerializable для класса(который в списке), так же перебрать список
3) сделать свой список и реализовать для него и класса IXmlSerializable

4) вообще забыть про serializer и писать через XmlWriter или XmlDocument
0
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
26.12.2010, 02:16  [ТС] 4
А как загрузить можно? Только попроще как нибудь, если можно.
Я пока только смог открыть документ и получить и как я понял передвинуться по дереву на элемент <ArrayOfTestObject/>
C#
1
2
3
4
5
6
7
8
9
10
            String path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "SaveFile.xml");
 
            List<TestObject> listLoaded;
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(path);
            XmlNode xmlNode = xmlDoc.DocumentElement;
            foreach (XmlNode node in xmlNode.ChildNodes)
            {
                string nodeName = node.Name; //это в дебагере смотрел, что там к чему у меня получается =)
            }
Вот сижу думаю, как там дальше делать дело =)

Добавлено через 2 минуты
Цитата Сообщение от m0nax Посмотреть сообщение
бывает разные уровни "ручнистости"

1) перебрать список и сериализовать каждый элемент обычным XmlsSerializer
2) реализовать IXmlSerializable для класса(который в списке), так же перебрать список
3) сделать свой список и реализовать для него и класса IXmlSerializable

4) вообще забыть про serializer и писать через XmlWriter или XmlDocument
Мне скорее подойдёт такой вариант:
Я сохраняю сериализацией всегда. При выходе новой версии гружу старые файлы вручную, через XmlDocument, конвертирую настройки и т.д. Создаю новый файл(ы) и потом уже читаю и сохраняю, как обычно сериализацией. Так проще думаю. Это в теории, а так предстоит это ещё опробовать, не известно, что там получится...
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
26.12.2010, 02:31 5
А как ты вообще умудрился сломать стандартный читатель?)
Он же прекрасно читает если нет(или есть лишние) каких-то полей в классе, даже если целый список каких-то объектов пропадет он все равно сможет прочитать
0
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
26.12.2010, 02:56  [ТС] 6
Ну например я изменил класс так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    [Serializable]
    public enum Mode : byte
    {
        Single, Int32, Decimal, Reader
    }
 
    [Serializable]
    public class TestObject
    {
        public float valueFloat { get; set; }
        public int valueInt { get; set; }
        public String valueText { get; set; }
        public DateTime valueDateTime { get; set; }
        public Mode enumMode { get; set; }
 
        public TestObject()
        {
        }
 
        public TestObject(int valInt, String valText, DateTime valDateTime, Mode enumMode, float valFloat)
        {
            this.valueInt = valInt;
            this.valueText = valText;
            this.valueDateTime = valDateTime;
            this.enumMode = enumMode;
            this.valueFloat = valFloat;
        }
    }
Уже не читает.

Добавлено через 22 минуты
О! Вроде разобрался более менее. Только, чтобы с EnumConverter небыло проблем в перечислении лучше не использовать зарезервированные слова, так как ругался при конвертации на значение Double

Чуть изменил перечисление и в файле тоже проставил эти изменённые значения:
C#
1
2
3
4
    public enum Mode : byte
    {
        AAA, BBB, CCC, DDD
    }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
            String path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "SaveFile.xml");
 
            List<TestObject> listLoaded = new List<TestObject>();
 
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(path);
 
            XmlNodeList xmlNodeList = xmlDoc.GetElementsByTagName("TestObject");
            for (int i = 0; i < xmlNodeList.Count; i++)
            {
                XmlElement El1 = (XmlElement)xmlDoc.GetElementsByTagName("valueInt")[i];
                XmlElement El2 = (XmlElement)xmlDoc.GetElementsByTagName("valueText")[i];
                XmlElement El3 = (XmlElement)xmlDoc.GetElementsByTagName("valueDateTime")[i];
                XmlElement El4 = (XmlElement)xmlDoc.GetElementsByTagName("enumMode")[i];
 
                DateTimeConverter dtConv = new DateTimeConverter();
                DateTime date = (DateTime)dtConv.ConvertFromString(El3.InnerText);
                EnumConverter enumConv = new EnumConverter(typeof(Mode));
                Mode mode = (Mode)enumConv.ConvertFromString(El4.InnerText);
 
                TestObject testObj = new TestObject(int.Parse(El1.InnerText), El2.InnerText, date, mode, 0f);
                listLoaded.Add(testObj);
            }
Кстати, как считаете это не слишком убогий способ? Ну просто тут прописаны жёстко названия элементов, хотя как по другому, я что-то не представляю.
0
1513 / 780 / 103
Регистрация: 22.04.2008
Сообщений: 1,610
27.12.2010, 21:53 7
Цитата Сообщение от Casper-SC Посмотреть сообщение
А как загрузить можно? Только попроще как нибудь, если можно.
Вот этот метод и читает данные из файла xml
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        public List<ProjectLog> GetProjects()
        {
            if (xDocument.Root != null)
            {
                var projects = from project in xDocument.Root.Descendants(ProjectEntry)
                               select new ProjectLog
                                          {
 
                                              ProjectId = project.Attribute("ProjectId").Value,
                                              UserId = project.Attribute("UserId").Value,
                                              DurationTime = TimeSpan.Parse(project.Attribute("DurationTime").Value),
                                              StartDate = DateTime.Parse(project.Attribute("StartDate").Value)
                                          };
                    
                return projects.ToList();
            }
            return new List<ProjectLog>();
 
        }
Пример использования
C#
1
2
3
4
//Создаем объект репозитория
ProjectLogXmlRepository rep = new ProjectLogXmlRepository("MyProjects.xml");
//Читаем данные
var projects = rep.GetProjects();
Добавлено через 55 секунд
Цитата Сообщение от Casper-SC Посмотреть сообщение
Кстати, как считаете это не слишком убогий способ?
Если хотите красивее используйте сериализацию
0
826 / 717 / 110
Регистрация: 06.10.2010
Сообщений: 825
Записей в блоге: 1
27.12.2010, 22:03 8
Вот тут:
https://www.cyberforum.ru/csha... ost1237754
есть пример без сериализации и то же самое с ней (чуть ниже). Может пригодится.
0
27.12.2010, 22:03
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.12.2010, 22:03
Помогаю со студенческими работами здесь

Комментарии при сериализации класса в xml
Здравствуйте. Вот я делаю серилизацию таким образом public bool SaveSettings() { ...

При сериализации класса, порой, меняется очерёдность полей в конечном XML файле
Доброго времени суток. При сериализации класса, порой, меняется очерёдность полей в конечном xml...

Сохранение объектов
Помогите, пожалуйста! В своем проекте я решила поменять формат сохранения данных. Сначала я...

сохранение объектов
Привет всем. У меня есть элемент TabControl, и в каждом TabPage я могу добавлять и удалять...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru