Файл: 1_C#_Введение_в_программирование_Уч_пособ_(Марченко-2005).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2025

Просмотров: 1390

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

SignatureToken

Предоставляет

Token,

возвращенный

метаданными

для

 

представления подписи.

 

 

 

StringToken

Предоставляет лексему, которая предоставляет строку.

 

TypeToken

Представляет маркер Token, который возвращается метаданными,

 

чтобы представить тип.

 

 

 

Перечисления

 

 

 

 

 

Перечисление

Описание

 

 

 

 

AssemblyBuilderAccess

Определяет режимы доступа для динамической сборки.

 

FlowControl

Описывает, каким образом инструкция меняет поток команд

 

управления.

 

 

 

 

OpCodeType

Описывает типы инструкций промежуточного языка MSIL.

 

OperandType

Описывает тип операнда инструкции промежуточного языка MSIL.

PackingSize

Задает один из двух факторов, определяющих выравнивание

 

занимаемой полями памяти при маршаллинге типа.

 

PEFileKinds

Задает тип переносимого исполняемого PE-файла.

 

StackBehaviour

Описывает, как значения помещаются в стек или выводятся из

 

стека.

 

 

 

 

Динамическая сборка: создание, сохранение, загрузка, выполнение

///-----------------------------------------------------------------------------------

///Вот такой класс в составе однофайловой сборки DynamicAssm

///предполагается построить в ходе выполнения сборки DynamicAssemblyGenerator.

///public class DynamicTest

///{

///private string messageString;

///// Конструктор

///DynamicTest(string strKey)

///{

///messageString = strKey;

///}

///

///// Методы

///public void ShowMessageString()

///{

///System.Console.WriteLine(“the value of messageString is {0}...”, messageString);

///}

///

///public string GetMessageString()

///{

///return messageString;

///}

///

///}

///-----------------------------------------------------------------------------------

using System;

using System.Reflection; using System.Reflection.Emit; using System.Threading;

namespace DynamicAssemblyGenerator

{

///<summary>

///AssemblyGenerator - класс, реализующий динамическую генерацию сборки.

///</summary>

class AssemblyGenerator

{

public string XXX; public string ZZZ()

{

return XXX;

}

public int CreateAssm(AppDomain currentAppDomain)

{

// Создание сборки начинается с присвоения ей имени и номера версии.

119


//Для этого используется класс AssemblyName.

//Определяется имя и версия создаваемой сборки. AssemblyName assmName = new AssemblyName(); assmName.Name = “DynamicAssm”;

assmName.Version = new Version(“1.0.0.0”);

//Создаётся сборка в памяти. В рамках текущего домена приложения.

//С использованием режима доступа, который задаётся одним из элементов перечисления:

//Run - динамическая сборка выполняется, но не сохраняется.

//RunAndSave - динамическая сборка выполняется и сохраняется.

//Save - динамическая сборка не выполненяется, но сохраняется.

AssemblyBuilder assembly = currentAppDomain.DefineDynamicAssembly(assmName, AssemblyBuilderAccess.Save);

//Создаётся однофайловая сборка, в которой имя единственного модуля совпадает с именем самой сборки.

ModuleBuilder module = assembly.DefineDynamicModule(“DynamicAssm”, «DynamicAssm.dll» );

//Создаётся и определяется класс DynamicTest класс. Метод module.DefineType позволяет

//встраивать в модуль класс, структуру или интерфейс.

//Вторым параметром метода идёт элемент перечисления. Таким образом создаётся объектзаготовка

//класса, который далее дополняется полями, свойствами, методами...

TypeBuilder dynamicTestClass = module.DefineType(“DynamicAssm.DynamicTest”, TypeAttributes.Public);

//Объявляется данное-член класса DynamicTest.

//Предполагается объявить “private string messageString;”

FieldBuilder messageStringField = dynamicTestClass.DefineField(“messageString”, Type.GetType(“System.String”),

FieldAttributes.Private);

//Объекты для генерации элементов класса. В данном конкретном случае используются при генерации:

ILGenerator bodyConstructorIL; // - тела конструктора. ILGenerator methodIL; // - тела метода.

//Объявляется конструктор.__________________________________________________________

//Предполагается объявить «DynamicTest(string strKey)...»

Type[] constructorArgs = new Type[1]; constructorArgs[0] = Type.GetType(“System.String”);

ConstructorBuilder constructor = dynamicTestClass.DefineConstructor( MethodAttributes.Public,

CallingConventions.Standard,

constructorArgs);

//Тело конструктора. Представляет собой IL код,

//который встраивается в тело конструктора посредством метода Emit,

//определённого в классе ILGenerator (см. Объекты для генерации элементов класса).

//Метод Emit в качестве параметров использует перечисление OpCodes (коды операций),

//которые определяют допустимые команды IL.

bodyConstructorIL = constructor.GetILGenerator(); bodyConstructorIL.Emit(OpCodes.Ldarg_0);

Type objectClass = Type.GetType(“System.Object”);

ConstructorInfo greatConstructor = objectClass.GetConstructor(new Type[0]); bodyConstructorIL.Emit(OpCodes.Call, greatConstructor); bodyConstructorIL.Emit(OpCodes.Ldarg_0); bodyConstructorIL.Emit(OpCodes.Ldarg_1); bodyConstructorIL.Emit(OpCodes.Stfld,messageStringField); bodyConstructorIL.Emit(OpCodes.Ret);

//Конец объявления конструктора.____________________________________________________

//Объявление метода public string GetMessageString()________________________________

MethodBuilder GetMessageStringMethod = dynamicTestClass.DefineMethod( “GetMessageString”,

MethodAttributes.Public,

Type.GetType(“System.Sring”),

null);

//IL_0000: ldarg.0

//IL_0001: ldfld string DynamicAssemblyGenerator.AssemblyGenerator::XXX

//IL_0006: stloc.0

//IL_0007: br.s IL_0009

//IL_0009: ldloc.0

//IL_000a: ret

120



//System.Reflection.Emit.Label label = new Label();

// Тело метода...

methodIL = GetMessageStringMethod.GetILGenerator(); methodIL.Emit(OpCodes.Ldarg_0); methodIL.Emit(OpCodes.Ldfld,messageStringField); methodIL.Emit(OpCodes.Ret);

//Конец объявления метода public string GetMessageString()___________________________

//Объявление метода public string ShowMessageString()________________________________

MethodBuilder ShowMessageStringMethod = dynamicTestClass.DefineMethod( “ShowMessageString”,

MethodAttributes.Public,

null,

null);

//Тело метода...

methodIL = ShowMessageStringMethod.GetILGenerator(); methodIL.EmitWriteLine(“This is ShowMessageStringMethod...”); methodIL.Emit(OpCodes.Ret);

//Конец объявления метода public string ShowMessageString()__________________________

//Вот и завершили динамическое объявление класса.

dynamicTestClass.CreateType();

// Остаётся его сохранить на диск. assembly.Save(“DynamicAssm.dll”);

return 0;

}

static void Main(string[] args)

{

//Создаётся и сохраняется динамическая сборка. AssemblyGenerator ag = new AssemblyGenerator(); ag.CreateAssm(AppDomain.CurrentDomain);

//Для наглядности! создаются НОВЫЕ объекты и заново добывается

//ссылка на текущий домен приложения.

//Теперь - дело техники. Надо загрузить и выполнить сборку.

//Делали. Умеем!

AppDomain currentAppDomain = Thread.GetDomain(); AssemblyGenerator assmGenerator = new AssemblyGenerator(); assmGenerator.CreateAssm(currentAppDomain);

// Загружаем сборку.

Assembly assm = Assembly.Load(“DynamicAssm”);

//Объект класса Type для класса DynamicTest. Type t = assm.GetType(“DynamicAssm.DynamicTest”);

//Создаётся объект класса DynamicTest и вызывается конструктор с параметрами. object[] argsX = new object[1];

argsX[0] = “Yes, yes, yes-s-s-s!”;

object obj = Activator.CreateInstance(t, argsX);

MethodInfo mi;

//«От имени» объекта-представителя класса DynamicTest

//вызывается метод ShowMessageString.

mi = t.GetMethod(“ShowMessageString”); mi.Invoke(obj,null);

//«От имени» объекта-представителя класса DynamicTest

//вызывается метод GetMessageString.

//Этот метод возвращает строку, которая перехватывается

//и выводится в окне консольного приложения.

mi = t.GetMethod(“GetMessageString”);

//!!!//mi.Invoke(obj,null);//Этот метод не вызывается. Криво объявился? //

}

}

}

121


Ввод-вывод

Базовые операции

В общем случае понятие ПОТОК это абстрактное понятие, которое обозначает динамическую изменяющуюся во времени последовательность чего-либо.

Применительно к обсуждаемым проблемам ввода-вывода в программах на C#, поток - это последовательность байтов, связанная с конкретными устройствами компьютера (диски, дисплей, принтер, клавиатура) посредством системы вводавывода.

Система ввода-вывода обеспечивает для программиста стандартные и не зависящие от физического устройства средства представления информации и управления потоками ввода-вывода. Действия по организации ввода-вывода обеспечивается стандартными наборами, как правило, одноименных функций вводавывода со стандартным интерфейсом (спецификацией возвращаемого значения и списком параметров).

Функции, обеспечивающие взаимодействие с различными устройствами вводавывода, объявляются в различных классах. Вопрос “ОТКУДА ВЫЗВАТЬ функцию” часто становится более важным, чем вопрос “КАК ПОСТРОИТЬ выражение вызова функции”.

Потоки: байтовые, символьные, двоичные

Большинство устройств, предназначенных для выполнения операций ввода-вывода, являются байт-ориентированными. Этим и объясняется тот факт, что на самом низком уровне все операции ввода-вывода манипулируют с байтами в рамках байтовых потоков.

С другой стороны, значительный объём работ, для которых, собственно и используется вычислительная техника, предполагает работу с символами, а не с байтами (заполнение экранной формы, вывод информации в наглядном и легко читаемом виде, текстовые редакторы).

Символьно-ориентированные потоки, предназначенные для манипулирования с символами, а не с байтами, являются потоками ввода-вывода более высокого уровня. В рамках Framework.NET определены соответствующие классы, которые при реализации операций ввода-вывода обеспечивают автоматическое преобразование данных типа byte в данные типа char и обратно.

В дополнение к байтовым и символьным потокам в C# определены два класса, реализующих механизмы считывания и записи информации непосредственно в двоичном представлении (потоки BynaryReader и BynaryWriter).

Общая характеристика классов потоков Основные особенности и правила работы с устройствами ввода-вывода в

современных языках высокого уровня описываются в рамках классов потоков. Для языков платформы .NET местом описания самых общих свойств потоков является класс System.IO.Stream.

Назначение этого класса заключается в объявлении общего стандартного набора операций (стандартного интерфейса), обеспечивающих работу с устройствами ввода-вывода, независимо от их конкретной реализации источников и получателей информации.

Процедуры чтения и записи информации определяется следующим (список неполон!) набором свойств и АБСТРАКТНЫХ методов, объявляемых в этом классе.

Здесь и ниже понятие АБСТРАКТНЫЙ означает отсутствие КОНКРЕТНОЙ реализации данного метода (об этом позже!). Классы, содержащие абстрактные методы, также называются абстрактными. Основная задача абстрактного класса – задать план для построения, общее направление реализации конкретных (неабстрактных) классов.

В рамках Framework.NET, независимо от характеристик того или иного устройства ввода-вывода, программист ВСЕГДА может узнать:

можно ли читать из потока – bool CanRead (если можно – значение должно быть установлено в true),

122