Главная » C# » Определение интерфейсов и реализация оболочки в Visual C# (Sharp)

0

В .NET существуют потоки данных двух типов: двоичных и текстовых. Типы Textwriter и TextReader используются для работы с потоками текстовых данных. Как было продемонстрировано типом stringReader, при работе с потоками текстых данных можно делать определенные предположения, например, где начинаюя текстовые строки. Но в случае с потоками двоичных данных такие предположия не являются возможными. Потоки двоичных данных имеют свои форматы, которые известны лишь программам, предназначенным для их создания и чтения.

Типы потоков двоичных данных можно использовать для обработки потоков тетовых данных, но  для  этого  требуется  знание  подробностей  о  потоке  данных. Не забывайте, что предоставляемая .NET система обработки текста способна рабать с разными кодовыми страницами Unicode. Кодовая страница Unicode претавляет собой специальную таблицу преобразований. Манипулируя самостоятело текстовыми потоками, используя типы  двоичных  потоков,  мы  говорим  .NET, что будем сами управлять подробностями кодовых  страниц Unicode. В действельности же мы не хотим этого делать и, значит, не должны смешивать потоки данных. Поэтому для нашего приложения нам потребуется создать два разных иерфейса: один для преобразования текстовых данных в двоичные, а другой для преобразования двоичных данных в текст.

ПРИМЕЧАНИЕ

Дополнительную информацию  о Unicode и  других аспектах, связанных с обработкой текста,   см.    в   разд.      International   Text   Display"   ("Вывод  текста   национальных   языков") в  MSDN по адресу http://msdn2.microsoft.com/en-us/library/ms776l3l.aspx.

Исходный код интерфейса iBinary2TextProcessor для преобразования текстовых данных в двоичные выглядит так:

using System.IO; namespace Binary2Text

{

public interface IBinary2TextProcessor {

void Process(Stream input, • TextWriter output);

}

}

Единственный метод Process ()  интерфейса iBinary2TextProcessor имеет два паметра:  поток  двоичных  данных  и  поток  текстовых данных.  Реализация  интеейса  iBinary2 Text Process or будет отвечать за считывание данных двоичного потока и сохранение их в текстовый поток.

Интерфейс iText2BinaryProcessor для преобразования текстового потока в двчный организован подобным образом, за исключением того, что типы потоков обращены.

using System.10; namespace Text2Binary

{

public interface IText2BinaryProcessor {

void Process(TextReader input, Stream output);

}

}

Идея, лежащая в основе обоих интерфейсов, заключается в том, чтобы концентроваться на пересылке данных из одного потока в другой.

Оболочка для обоих интерфейсов потоков очень похожа на оболочку для потока обработки текста, за исключением того, что обрабатываются двоичный и текстый потоки. Оболочка TextProcessor должна была знать происхождение потока: консоль или файл. При работе с двоичными потоками необходимость знать истоик данных продолжает существовать, но вместо текстовых потоков создаются двоичные. Если вы понимаете механику использования текстовых потоков, то тае должны понимать механику работы с двоичными потоками.

Далее приводится полный код для реализации класса для  преобразования текстых  данных  в  двоичные.  (Необходимо  добавить  ссылку  на  проект  Text2Binary В проект е  ReaderWriter.)

using System.IO; using Text2Binary;

namespace ReaderWriter {

public static class Text2BinaryBootstrap { public static void DisplayHelp() {

Console.WriteLine("Нужна помощь? Прямо сейчас?");

}

public static void Process(string[] args,

IText2BinaryProcessor processor) { TextReader reader = null;

Stream writer = null;

if (args.Length == 0) { reader = Console.In;

writer = Console.OpenStandardOutput();

}

else if (args.Length == 1) { if (args[0] == "-help") {

DisplayHelp(); return;

}

else {

reader = File.OpenText(args[0]);

writer = Console.OpenStandardOutput();

}

}

else if (args.Length ==2 ) { if (args[0] == "-out") { reader = Console.In;

writer = F±le.0pen(args[l], FileMode.Create);

}

else {

DisplayHelp(); return;

}

}

else if (args.Length == 3) { if (args[0] == "-out") {

reader = File.OpenText(args[2]);

writer = File.Open(args[1], FileMode.Create);

}

else {

DisplayHelp(); return;

}

}

else {

DisplayHelp(); return;

}

processor.Process(reader, writer); writer.Close();

#if DEBUG_OUTPUT

Console.WriteLine)"Argument count(" + args.Length + ")"); foreach (string argument in args) {

Console.WriteLine("Argument (" + argument + ")");

}

#endif

}

}

}

Данная реализация почти идентична реализации класса Bootstrap; расхождения выделены жирным шрифтом. Обратите внимание на то, что вместо предопределеого члена данных console.out вызывается метод OpenStandardOutput (), а вместо метод а  FileCreateText ()   — мето д File. Open ().

Реализация оболочки преобразования двоичного потока в текстовый почти идеична реализации оболочки преобразования текстового потока в двоичный. Ее иодный код можно найти в исходном коде для книги, который  можно  загрузить через Интернет.

Определение типа

Центральной задачей при преобразовании текстового потока в двоичный и наобот является определение типа. Тип может быть классом (class) или структурой (struct) и определяется как тип, доступный для чтения и  записи.  Определение типа доступным для чтения и записи необходимо для того, чтобы когда .NET осуществляет его чтение или запись, зависимая инфраструктура знала, что делать.

Не забывайте, что поток двоичных данных является данными только тогда, когда программа знает, что он означает. Чтобы помочь .NET с чтением и записью этих типов, мы добавляем идентификаторы, которые указывают .NET, что нужно дать. К счастыб, для этого не требуется знать внутренние подробности процесса преобразования в двоичную форму, а только дать .NET общее представление о том, как управлять им.

Для  примера предсказания лотерейных номеров мы определим тип,  представляий лотерейный билет. Билет будет содержать дату тиража, обычные номера и бусный номер. Далее приводится полный исходный код объявления данного типа: namespace LottoLibrary {

[Serializable]

public class Ticket { int[] _numbers;

int _bonus;

DateTime _drawDate;

public Ticket() { >

public Ticket(DateTime drawDate, int[] numbers, int bonus) {

_drawDate = drawDate;

_numbers = numbers;

_bonus = bonus;

}

public DateTime DrawDate { get {

return _drawDate;

}

set {

_drawDate = value;

}

}

public int[] Numbers { get {

return _numbers;

}

set {

_numbers = value;

}

}

public int Bonus { get {

return _bonus;

}

set {

_bonus = value;

}

}

}

}

Тип Ticket для представления лотерейного билета является самым обычным клаом данных.  Но  выделенный жирным  шрифтом  код требует объяснений.  Первым случаем  такого  кода  является  заключенный  в  квадратные  скобки  идентификатор serializabie, который представляет атрибут .NET. В .NET имеется возможность описывать типы, методы и т. д. Атрибуты — это описания, используемые в опреденном контексте. В отличие от идентификаторов public и abstract, которые опывают основное поведения типа, атрибут serializabie описывает поведение типа в  конкретном  контексте — когда объект нужно  преобразовать  из  памяти  в  поток данных и  наоборот. Описания основного поведения важны для среды исполнения

.NET. Атрибуты .NET такой важности для среды не представляют, но имеют ваость для исполняемых средой библиотек.

При объявлении типа атрибут serializabie описывает возможность его сериалации. Для преобразования объекта Ticket в двоичный поток программисту не нужно ничего делать, кроме  как передать объект потоку данных. Подробностями преобразования будут заниматься библиотеки потока данных.

В объявлении  Ticket не имеющий параметров конструктор выделен жирным шрифтом, чтобы подчеркнуть, что такой тип конструктора необходим при преобровании потока данных в объект. Когда двоичные потоки  восстанавливают типы, они создают экземпляр пустого объекта, после чего присваивают значения членам данным. Поэтому для создания объекта требуется конструктор без параметров.

Источник: Гросс  К. С# 2008:  Пер. с англ. — СПб.:  БХВ-Петербург, 2009. — 576 е.:  ил. — (Самоучитель)

По теме:

  • Комментарии