|
При выполнении в лабораторной работе упражнения №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 все равно сам связывается с файлом, только он используется другим классом, выполняющим передачу данных в специфическом формате (сериализованных).
-
Разберитесь с кодом







