Файл: 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