При выполнении в лабораторной работе упражнения №1 , а именно при выполнении нижеследующего кода: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Microsoft.Xna.Framework.Graphics;
namespace Application1 { public partial class MainForm : Form { // Объявим поле графического устройства для видимости в методах GraphicsDevice device;
public MainForm() { InitializeComponent();
// Подпишемся на событие Load формы this.Load += new EventHandler(MainForm_Load);
// Попишемся на событие FormClosed формы this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed); }
void MainForm_FormClosed(object sender, FormClosedEventArgs e) { // Удаляем (освобождаем) устройство device.Dispose(); // На всякий случай присваиваем ссылке на устройство значение null device = null; }
void MainForm_Load(object sender, EventArgs e) { // Создаем объект представления для настройки графического устройства PresentationParameters presentParams = new PresentationParameters(); // Настраиваем объект представления через его свойства presentParams.IsFullScreen = false; // Включаем оконный режим presentParams.BackBufferCount = 1; // Включаем задний буфер // для двойной буферизации // Переключение переднего и заднего буферов // должно осуществляться с максимальной эффективностью presentParams.SwapEffect = SwapEffect.Discard; // Устанавливаем размеры заднего буфера по клиентской области окна формы presentParams.BackBufferWidth = this.ClientSize.Width; presentParams.BackBufferHeight = this.ClientSize.Height;
// Создадим графическое устройство с заданными настройками device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware, this.Handle, presentParams); }
protected override void OnPaint(PaintEventArgs e) { device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);
base.OnPaint(e); } } } Выбрасывается исключение: Невозможно загрузить файл или сборку "Microsoft.Xna.Framework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=6d5c3888ef60e27d" или один из зависимых от них компонентов. Не удается найти указанный файл. Делаю все пунктуально. В чем может быть проблема? |
Работа с потоками данных
Упражнение 3. Сериализация данных в потоке FileStream
В предыдущем упражнении мы записывали в поток (файл) разные типы данных, представленные разным количеством байтов. И сами должны были следить за тем, чтобы записанное правильно потом считать и интерпретировать. Обычно так не делают и записывают в файл однотипные данные. Так легче ослеживать размеры данных. Но если уж пришлось чередовать в одном потоке различные данные, то лучше для этого воспользоваться сериализацией.
Сериализация - это высокоуровневая модель, встроенная в потоки .NET, которая позволяет преобразовать объект целиком в последовательность байт, сохранить его в файле, базе данных или другом источнике, а затем прочитать и полностью восстановить (десериализовать).
Для поддержки сериализации объекту необходимо следующее:
- Наличие атрибута Serializable перед объявлением класса (типа)
- Поля класса должны быть сериализуемы, что для значимых (в отличие от ссылочных!) типов всегда выполнимо
- Если сериализуется производный класс, то вся предшествующая цепочка наследования тоже должна состоять из сериализуемых классов
Для выполнения сериализации библиотека .NET Framework имеет три класса:
- BinaryFormatter - сериализует объект в компактном двоичном представлении
- SoapFormatter - сериализует объект в текстовое представление на основе XML
- XmlSerializer - сериализует объект в текстовое представление на основе 'чистого' XML
Рассмотрим эти способы на предыдущем примере, чуток изменив сохраняемые данные.
- Командой File/Add/New Project добавьте к решение новый проект согласно следующему снимку мастера
- В панели Solution Explorer вызовите контекстное меню для узла App3 и выполните команду Set as StartUp Project, чтобы назначить проект стартовым
- В панели Solution Explorer выделите узел App3 и щелкните на пиктограмме Properties, чтобы открыть панель конструктора проектов
- На вкладке Application установите выпадающий список Output type в значение Console Application, включив параллельно окну формы еще и консоль для вывода информации
- В режиме Design конструктора форм поместите на форму из панели Toolbox интерфейсные элементы управления и настройте их в соответствии с таблицей свойств
Добавьте текстовые метки для заголовков и настройте их по своему вкусу. Интерфейс формы должен выглядеть так
Мы подготовили интерфейс пользователя, который больше менять не будем. Поэтому разумно будет его замкнуть, чтобы защитить от случайных изменений.
- В режиме Design конструктора форм выполните команду Edit/Select All, а затем - команду Format/Lock Controls, элементы интерфейса станут недоступными для редактирования в графическом режиме проектирования
- Последовательно двойным щелчком на каждом экземпляре объекта LinkLabel создайте заготовки обработчиков и их регистрацию для событий LinkClicked
Для тренировки мы уберем регистрацию обработчиков, созданную автоматически в файле Form1.Designer.cs, и перенесем ее в конструктор класса формы. Для этого
- Внесите в заготовки обработчиков хотя бы комментарии, чтобы при выполнении следующего действия оболочка их не удалила
- В режиме Design выделите на форме последовательно объекты LinkLabel, в панели Properties щелкните на пиктограмме Events и очистите поля события LinkClicked
Библиотечные классы BinaryFormatter, SoapFormatter, XmlSerializer находятся в отдельных сборках: mscorlib.dll, System.Runtime.Serialization.Formatters.Soap.dll и System.Xml.dll соответственно. Они сгруппированы в пространствах имен System.Runtime.Serialization.Formatters.Binary, System.Runtime.Serialization.Formatters.Soap и System.Xml.Serialization. Библиотека mscorlib.dll является основной и всегда подключена к проектам оболочки. Библиотека System.Xml.dll тоже подключается при создании проекта, а вот System.Runtime.Serialization.Formatters.Soap.dll нужно подключить самостоятельно.
- В панели Solution Explorer вызовите контекстное меню для узла References проекта App3, командой Add Reference вызовите одноименное окно и подключите библиотеку System.Runtime.Serialization.Formatters.Soap.dll
- В панели Solution Explorer вызовите контекстное меню для узла App3 и командой Add/Class добавьте к проекту новый файл с именем DataObject.cs, который заполните так
using System; using System.Collections.Generic; using System.Text; namespace App3 { [Serializable()] // Атрибут public class DataObject { // Сохраняемые данные string stringData = "Привет всем!"; int integerData = (int)12345; float floatData = 67F; double doubleData = 89D; DateTime date; // Инициализируем в конструкторе // Конструкторы public DataObject(string message) { this.stringData = message; this.date = DateTime.Now; } public DataObject() { this.date = DateTime.Now; } // Свойства доступа к полям public String StringData { get { return stringData; } set { stringData = value; } } public Int32 IntegerData { get { return integerData; } set { integerData = value; } } public Single FloatData { get { return floatData; } set { floatData = value; } } public Double DoubleData { get { return doubleData; } set { doubleData = value; } } public DateTime Date { get { return date; } set { date = value; } } } }
- Модифицируйте файл Form1.cs, чтобы он стал таким
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; // Дополнительные пространства имен using System.IO; using System.Runtime.Serialization.Formatters.Binary; // Для класса BinaryFormatter using System.Runtime.Serialization.Formatters.Soap; // Для класса SoapFormatter using System.Xml.Serialization; // Для класса XmlSerializer namespace App3 { public partial class Form1 : Form { String fileNameBinary = "DataBinary.dat"; // Без пути - будет создан в каталоге сборки String fileNameSoap = "DataSoap.dat"; // Без пути - будет создан в каталоге сборки String fileNameXml = "DataXml.dat"; // Без пути - будет создан в каталоге сборки public Form1() { InitializeComponent(); // Настраиваем консоль Console.ForegroundColor = ConsoleColor.White; Console.Title = "Упражнение 3. Сериализация объектов"; // Регистрируем обработчики вручную saveBinary.LinkClicked += saveBinary_LinkClicked; loadBinary.LinkClicked += loadBinary_LinkClicked; saveSoap.LinkClicked += saveSoap_LinkClicked; loadSoap.LinkClicked += loadSoap_LinkClicked; saveXml.LinkClicked += saveXml_LinkClicked; loadXml.LinkClicked += loadXml_LinkClicked; } private void saveBinary_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { FileMode mode = FileMode.Create; if (new FileInfo(fileNameBinary).Exists) mode = FileMode.Append; // Будем добавлять! using (FileStream fs = new FileStream(fileNameBinary, mode)) { // Создаем объект с данными DataObject data = new DataObject(); // Создаем форматировщик BinaryFormatter formatter = new BinaryFormatter(); // Сериализуем объект в файл formatter.Serialize(fs, data); } } private void loadBinary_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { if (!File.Exists(fileNameBinary)) { MessageBox.Show("Нет данных для отображения", "Предупреждение", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } using (FileStream fs = new FileStream(fileNameBinary, FileMode.Open)) { // Создать форматировщик BinaryFormatter formatter = new BinaryFormatter(); // Прочитать и десериализовать все экземпляры объекта в файле Console.Clear(); while (fs.Position < fs.Length) { // Прочитать, десериализовать и переместить указатель на следующий объект DataObject data = (DataObject)formatter.Deserialize(fs); // Распечатать Console.WriteLine(data.StringData); Console.WriteLine(data.IntegerData); Console.WriteLine(data.FloatData); Console.WriteLine(data.DoubleData); Console.WriteLine(data.Date.ToString()); } } } private void saveSoap_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { FileMode mode = FileMode.Create; if (new FileInfo(fileNameSoap).Exists) mode = FileMode.Append; // Будем добавлять! using (FileStream fs = new FileStream(fileNameSoap, mode)) { // Создаем объект с данными DataObject data = new DataObject(); // Создаем форматировщик SoapFormatter formatter = new SoapFormatter(); // Сериализуем объект в файл formatter.Serialize(fs, data); } } private void loadSoap_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { if (!File.Exists(fileNameSoap)) { MessageBox.Show("Нет данных для отображения", "Предупреждение", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } using (FileStream fs = new FileStream(fileNameSoap, FileMode.Open)) { // Создать форматировщик SoapFormatter formatter = new SoapFormatter(); // Прочитать все сериализованные объекты Console.Clear(); while (fs.Position < fs.Length) { // Десериализовать DataObject data = (DataObject)formatter.Deserialize(fs); // Распечатать Console.WriteLine(data.StringData); Console.WriteLine(data.IntegerData); Console.WriteLine(data.FloatData); Console.WriteLine(data.DoubleData); Console.WriteLine(data.Date.ToString()); } } } private void saveXml_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { // Создаем или усекаем файл using (FileStream fs = new FileStream(fileNameXml, FileMode.Create)) { // Создаем объект с данными DataObject data = new DataObject(); // Создаем форматировщик XmlSerializer formatter = new XmlSerializer(typeof(DataObject)); // Сериализуем объект в файл formatter.Serialize(fs, data); } } private void loadXml_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { if (!File.Exists(fileNameXml)) { MessageBox.Show("Нет данных для отображения", "Предупреждение", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } using (FileStream fs = new FileStream(fileNameXml, FileMode.Open)) { // Создать форматировщик XmlSerializer formatter = new XmlSerializer(typeof(DataObject)); Console.Clear(); // Прочитать и десериализовать DataObject data = (DataObject)formatter.Deserialize(fs); // Распечатать Console.WriteLine(data.StringData); Console.WriteLine(data.IntegerData); Console.WriteLine(data.FloatData); Console.WriteLine(data.DoubleData); Console.WriteLine(data.Date.ToString()); } } } }
- Запустите приложение и испытайте все три способа - объект с данными сохраняется в файле и полностью восстанавливается
Обратите внимание на важную особенность приведенного вывода: показано время 92729 - симметричное число, хороший знак свыше ('верной дорогой идете товарищи')!
- В панели Solution Explorer выделите узел App3, щелкните на пиктограмме Show All Files, выделите файлы DataBinary.dat, DataSoap.dat и DataXml.dat (если они созданы)
- Командой Open контекстного меню панели Solution Explorer откройте эти файлы и ознакомтесь с форматом хранения сериализованной информации
Файловый поток FileStream все равно сам связывается с файлом, только он используется другим классом, выполняющим передачу данных в специфическом формате (сериализованных).
- Разберитесь с кодом