Алексей
Федоров
КомпьютерПресс 2'2002
Класс
Console и консольные приложения
Пространство имен System
Класс
Object
Класс
Type и пространство имен Reflection
В
двух предыдущих частях данной статьи мы начали знакомство с Microsoft
.NET Framework — ключевым компонентом Microsoft .NET, представляющим
собой платформу для создания, внедрения и выполнения Web-сервисов
и приложений. Мы рассказали об основных компонентах Microsoft .NET
Framework и кратко описали их назначение. Мы также начали более
подробное рассмотрение Common Language Runtime (CLR) — среды выполнения
.NET-приложений. Завершили мы знакомство с Common Language Runtime
рассказом о Common Type System.
В
этом номере мы начнем знакомство с библиотекой классов, рассмотрим
основные составляющие ее пространства имен и классы и приведем некоторые
примеры их использования.
Библиотека
классов .NET Framework Class Library содержит классы, обеспечивающие
следующие функции:
- поддержку
базовых и определяемых пользователями типов;
- поддержку
обработки исключительных ситуаций;
- операции
ввода/вывода и работу с потоками;
- обращение
к функциям операционной системы;
- доступ к
данным;
- возможность
создания Windows-приложений;
- возможность
создания клиентских и серверных Web-приложений;
- возможность
создания Web-сервисов.
Все
классы, реализованные в .NET Framework Class Library организованы
в виде пространств имен (namespaces). Каждое пространство имен содержит
классы и другие типы, которые относятся к специфическим задачам
или группе задач — операциям ввода/вывода, созданию Web-приложений,
работе с данными и XML-документами и т.п. В таблице показаны наиболее
важные пространства имен в библиотеке классов .NET.

После
краткого обзора основных пространств имен мы готовы приступить к
более детальному рассмотрению библиотеки классов .NET. Первая остановка
в нашем путешествии будет не совсем обычной — вместо традиционного
рассмотрения базового класса Object, который служит предком всех
классов в библиотеке классов .NET, мы рассмотрим класс Console и
консольные приложения. Почему мы поступаем именно так, будет понятно
чуть позже.
Класс
Console и консольные приложения
Используя
класс System.Console, мы можем создавать простейшие приложения для
среды .NET — консольные приложения, которые используют системное
окно для ввода и вывода информации и не требуют графического интерфейса.
Так как большинство примеров в данном цикле будет использовать консольные
приложения, мы начнем наше знакомство с библиотекой классов с класса
Console.
Класс
Console представляет собой стандартные потоки ввода, вывода и сообщений
об ошибках. Приложения, использующие данный класс, могут читать
символы из стандартного потока ввода (input stream) и выводить символы
в стандартный поток вывода (output stream). Ошибки выводятся в стандартный
поток сообщений об ошибках (error output stream). Эти три потока
автоматически ассоциируются с консолью при запуске приложения и
могут быть определены через свойства In, Out и Error класса Console.
По умолчанию стандартный поток ввода — это объект типа System.IO.TextReader,
а потоки вывода и сообщений об ошибках — объекты типа System.IO.
TextWriter. При необходимости мы можем переопределить эти потоки
в файловые потоки, сетевые потоки, потоки в памяти и т.п.
Используя
Visual Basic .NET, мы создаем консольное приложение как новый модуль,
который содержит подпрограмму с именем Main — она является точкой
входа в наше консольное приложение:
'---------------------------------------
' .NET – Консольное приложение
'---------------------------------------
Imports System
Module Cons
Sub Main()
Console.WriteLine(".NET Console application")
Console.ReadLine()
End Sub
End Module
Методы
Read и ReadLine служат для чтения одного или более символов или
символа новой строки из стандартного потока ввода, а методы Write
и WriteLine — для вывода одного или более символов либо строки с
символом новой строки в стандартный поток вывода.

Методы
SetIn, SetOut и SetError позволяют переопределить стандартные потоки
ввода, вывода и ошибок. Эти методы ожидают аргумент типа TextWriter,
который описывает поток.
Теперь
мы полностью готовы начать изучение Microsoft .NET Class Library.
В следующем разделе мы рассмотрим пространство имен System и его
дочерние пространства имен.
Пространство
имен System
Пространство
имен System является корневым пространством имен в Microsoft .NET
Class Library и содержит фундаментальные типы данных, реализованные
в .NET Framework. Это пространство имен содержит класс Object, который
служит предком для всех классов в библиотеке классов .NET, примитивные
и расширенные типы, а также более 100 дополнительных классов, используемых
для обработки исключительных ситуаций, управления доменами приложений,
сборки мусора и т.п.
Класс
Object
Класс
System.Object служит предком для всех классов в библиотеке классов
.NET. Методы, реализованные в данном классе, показаны на следующем
рисунке.

Кратко
рассмотрим каждый из этих методов:
- Метод Equals
(Object) или Equals (Object, Object) — служит для проверки, являются
ли два объекта одним и тем же экземпляром. Для данных со значениями
этот метод переопределен (в классе ValueType) и позволяет проверить
идентичность хранимых экземплярами объекта значений. Обратите
внимание: когда мы сравниваем два ссылочных типа, метод Equals
проверяет, являются ли оба экземпляра идентичными; для данных
со значениями метод Equals также проверяет идентичность данных,
хранимых экземплярами объекта.
- Метод ReferenceEquals
(Object, Object) проверяет, являются ли два объекта одним и тем
же экземпляром класса.
- Метод Finalize()
по умолчанию не выполняет никаких действий. Этот метод может быть
переопределен в унаследованных классах для выполнения финальной
очистки памяти перед тем, как механизм сборки мусора (Garbage
Collector) уничтожит данный объект.
- Метод GetHashCode()
служит для генерации хэш-значений (типа Integer), которые могут
быть использованы для хранения объектов в хэш-таблицах.
- Метод MemberwiseClone()
создает точную копию объекта.
- Метод ToString()
возвращает текстовое представление объекта. В большинстве случаев
этот метод возвращает полное имя класса для данного объекта.
- Метод GetType()
возвращает объект типа Type для данного экземпляра класса.
Ниже
мы расскажем, как используется класс Type.
Класс
Type и пространство имен Reflection
Класс
Type является нашей точкой входа в пространство имен Reflection.
Отражение (Reflection) в терминах .NET — это способность изучать
возможности классов во время выполнения программы. Используя отражения,
мы можем извлекать классы, изучать их методы, свойства, конструкторы,
поля, события и другие члены, одним словом, получаем доступ к метаданным,
ассоциированным с данным классом.
Класс
Type содержит методы типа GetMethods() и GetProperties(), которые
могут использоваться для получения информации о членах класса. Используя
классы, реализованные в пространстве имен Reflection, мы можем получать
сведения, например, о параметрах методов (используя класс System.Reflection.
MethodInfo) и даже вызывать методы с помощью метода Invoke().
В
следующем примере показано, как начать использовать механизм отражений.
Приведенный ниже код показывает, как с помощью метода GetType()
получить объект Type и каким образом можно применять ряд свойств
этого объекта:
'-------------------------------------------
' .NET Пример использования метода GetType
'-------------------------------------------
Imports System
Imports System.Reflection
Module Cons
Sub Main()
Dim I As Integer
Dim T As Type
T = I.GetType()
Console.WriteLine("Name = " & T.Name)
Console.WriteLine("Module = " & T.Module.ToString())
Console.WriteLine("Namespace = " & T.Namespace)
End Sub
End Module

Кратко
рассмотрим основные возможности, предоставляемые пространством имен
Reflection, а затем проиллюстрируем некоторые из них примерами.
- Класс Assembly
можно использовать для определения и загрузки сборок, загрузки
модулей из манифеста сборки (assembly manifest), поиска типов,
описанных в сборке, и создания экземпляров этих типов.
- Класс Module
можно использовать для поиска классов в модуле, а также всех глобальных
и локальных методов, определенных в данном модуле.
- Класс ConstructorInfo
можно использовать для поиска имен, параметров, модификаторов
доступа и другой информации о конструкторе. Поиск и вызов конструкторов
мы можем осуществлять с помощью методов GetConstructors() или
GetConstructor() объекта Type.
- Класс MethodInfo
используется для поиска имен, возвращаемых типов, параметров,
модификаторов доступа и другой информации о методе. Поиск и вызов
методов мы можем осуществлять с помощью методов GetMethods() или
GetMethod() объекта Type.
- Для поиска
информации о полях — именах, модификаторах доступа и т.п. — используется
класс FieldInfo. Кроме того, с помощью данного класса мы можем
получать и задавать значения полей.
- Класс EventInfo
используется для поиска имен, типов данных обработчиков событий
и другой информации о событии. Данный класс позволяет добавлять
и удалять обработчики событий.
- Класс PropertyInfo
используется для поиска имен, типов данных и другой информации
о свойствах. С помощью данного класса мы также можем получать
и задавать значения свойств.
- Класс ParameterInfo
используется для поиска информации о параметрах — названии, типе
данных, и т.п.
В
следующем примере показано, как получить список типов, определенных
в данном модуле.
'-------------------------------------------
' .NET – Пример использования "отражений"
'-------------------------------------------
Imports System
Imports System.Reflection
Module Cons
Sub Main()
Dim I As Integer
Dim T As Type
Dim Types() As Type
Dim M As [Module]
T = I.GetType()
M = T.Module
Types = M.GetTypes()
For Each T In Types
Console.WriteLine(T.FullName)
Next
End Sub
End Module
Ниже
показана выводимая данным кодом информация:
.
Как
видно из вышеприведенного списка, в целом концепция отражений напоминает
использование интерфейса ITypeLibrary в Win32 API для исследования
библиотек типов, но версия для .NET предоставляет больше возможностей,
более проста в использовании и более дружественна к различным языкам
программирования.
Теперь
расширим наш пример и добавим информацию о свойствах, конструкторах,
методах, интерфейсах и событиях. Для этого воспользуемся методами
GetProperties(), GetConstructors(), GetMethods(), GetInterfaces()
и GetEvents() объекта Type. Каждый из этих методов возвращает массив
элементов типа PropertyInfo, MethodInfo, EventInfo и т.п. — каждый
тип наследует от абстрактного типа MemberInfo, который мы и используем
в нашем примере. Исключение составляет только тип PropertyInfo —
этот тип используется для того, чтобы получить дополнительную информацию
о свойствах:
'-------------------------------------------
' .NET – Пример использования "отражений"
'-------------------------------------------
Imports System
Imports System.Reflection
Module Cons
Sub Main()
Dim T As Type
Dim MI As MemberInfo
Dim Types() As Type
Dim Members() As MemberInfo
Dim M As [Module]
Dim PI As PropertyInfo
Dim PText As String
T = Type.GetType("System.Array")
Console.WriteLine("{0} : {1}", GetTypeDescription(T), T)
'
' Показать все свойства
'
Console.WriteLine("---- Свойства ----")
Members = T.GetProperties
For Each MI In Members
PI = MI
If PI.CanRead And PI.CanWrite Then
PText = "get; set;"
Else
If PI.CanRead Then
PText = "get"
Else
If PI.CanWrite Then
PText = "set"
End If
End If
End If
Console.WriteLine("{0} {1} : {2} {3}", vbTab, "Prop", _
PText, MI.ToString)
Next
'
' Показать все конструкторы
'
Console.WriteLine("---- Конструкторы ----")
Members = T.GetConstructors(BindingFlags.Public Or _
BindingFlags.Static Or BindingFlags.NonPublic Or _
BindingFlags.Instance)
For Each MI In Members
Console.WriteLine("{0} {1} : {2}", vbTab, "Meth", _
MI.ToString)
Next
'
' Показать все методы
'
Console.WriteLine("---- Методы ----")
Members = T.GetMethods
For Each MI In Members
Console.WriteLine("{0} {1} : {2}", vbTab, "Meth", MI)
Next
'
' Показать все интерфейсы
'
Console.WriteLine("---- Интерфейсы ----")
Members = T.GetInterfaces
For Each MI In Members
Console.WriteLine("{0} {1} : {2}", vbTab, "Intf", _
MI.ToString)
Next
'
' Показать все события
'
Console.WriteLine("---- События ----")
Members = T.GetEvents
For Each MI In Members
Console.WriteLine("{0} {1} : {2}", vbTab, "Evnt", _
MI.ToString)
Next
'Next
End Sub
Private Function GetTypeDescription(ByVal aType As Type) As String
Dim str As String = Nothing
If aType.IsClass Then
str = "Class"
End If
If aType.IsInterface Then
str = "Interface"
End If
If aType.IsValueType Then
str = "Struct"
End If
If aType.IsArray Then
str = "Array"
End If
Return str
End Function 'GetTypeDescription
End Module
Ниже
показана информация, выводимая нашим примером для класса System.Array:
Class : System.Array
---- Свойства ----
Prop : get Int32 Length
Prop : get Int32 Rank
Prop : get System.Object SyncRoot
Prop : get Boolean IsReadOnly
Prop : get Boolean IsFixedSize
Prop : get Boolean IsSynchronized
---- Конструкторы ----
Meth : Void .ctor()
---- Методы ----
Meth : System.Collections.IEnumerator GetEnumerator()
Meth : Boolean get_IsSynchronized()
Meth : System.Object get_SyncRoot()
Meth : Void CopyTo(System.Array, Int32)
Meth : Boolean get_IsFixedSize()
Meth : Boolean get_IsReadOnly()
Meth : System.Object Clone()
Meth : Int32 GetHashCode()
Meth : Boolean Equals(System.Object)
Meth : System.String ToString()
Meth : System.Array CreateInstance(System.Type, Int32)
Meth : System.Array CreateInstance(System.Type, Int32, Int32)
Meth : System.Array CreateInstance(System.Type, Int32, Int32, Int32)
Meth : System.Array CreateInstance(System.Type, Int32[])
Meth : System.Array CreateInstance(System.Type, Int32[], Int32[])
Meth : Void Copy(System.Array, System.Array, Int32)
Meth : Void Copy(System.Array, Int32, System.Array, Int32, Int32)
Meth : Void Clear(System.Array, Int32, Int32)
Meth : System.Object GetValue(Int32[])
Meth : System.Object GetValue(Int32)
Meth : System.Object GetValue(Int32, Int32)
Meth : System.Object GetValue(Int32, Int32, Int32)
Meth : Void SetValue(System.Object, Int32)
Meth : Void SetValue(System.Object, Int32, Int32)
Meth : Void SetValue(System.Object, Int32, Int32, Int32)
Meth : Void SetValue(System.Object, Int32[])
Meth : Int32 get_Length()
Meth : Int32 GetLength(Int32)
Meth : Int32 get_Rank()
Meth : Int32 GetUpperBound(Int32)
Meth : Int32 GetLowerBound(Int32)
Meth : Int32 BinarySearch(System.Array, System.Object)
Meth : Int32 BinarySearch(System.Array, Int32, Int32, System.Object)
Meth : Int32 BinarySearch(System.Array, System.Object,
System.Collections.IComparer)
Meth : Int32 BinarySearch(System.Array, Int32, Int32, System.Object,
System.Collections.IComparer)
Meth : Int32 IndexOf(System.Array, System.Object)
Meth : Int32 IndexOf(System.Array, System.Object, Int32)
Meth : Int32 IndexOf(System.Array, System.Object, Int32, Int32)
Meth : Int32 LastIndexOf(System.Array, System.Object)
Meth : Int32 LastIndexOf(System.Array, System.Object, Int32)
Meth : Int32 LastIndexOf(System.Array, System.Object, Int32, Int32)
Meth : Void Reverse(System.Array)
Meth : Void Reverse(System.Array, Int32, Int32)
Meth : Void Sort(System.Array)
Meth : Void Sort(System.Array, System.Array)
Meth : Void Sort(System.Array, Int32, Int32)
Meth : Void Sort(System.Array, System.Array, Int32, Int32)
Meth : Void Sort(System.Array, System.Collections.IComparer)
Meth : Void Sort(System.Array, System.Array, System.Collections.IComparer)
Meth : Void Sort(System.Array, Int32, Int32, System.Collections.IComparer)
Meth : Void Sort(System.Array, System.Array, Int32, Int32,
System.Collections.IComparer)
Meth : Void Initialize()
Meth : System.Type GetType()
---- Интерфейсы ----
Intf : System.ICloneable
Intf : System.Collections.IList
Intf : System.Collections.ICollection
Intf : System.Collections.IEnumerable
Обратите
внимание на то, что параметры методов не имеют названий — в листинге
показаны только типы данных. Чтобы получить более подробную информацию
о параметрах методов, мы должны воспользоваться методом GetParameters()
и структурой ParameterInfo. Как это сделать, показано ниже:
'
' Показать все методы
'
Console.WriteLine("---- Методы ----")
Members = T.GetMethods
For Each MI In Members
PAInfo = CType(MI, MethodInfo).GetParameters
If PAInfo.Length > 0 Then
Console.WriteLine("{0} {1} : {2}{3}", vbTab, "Meth", MI.Name, "(")
For Each PAI In PAInfo
Console.WriteLine(" {0} {1} : {2}", vbTab, PAI.Name, _
PAI.ParameterType.ToString)
Next
Console.WriteLine("{0}{1}", vbTab, ")")
Else
Console.WriteLine(" {0} {1} : {2}{3}", vbTab, "Meth", MI.Name, _
"()")
End If
Next
Теперь
мы знаем названия параметров и их тип:
---- Методы ----
Meth : GetEnumerator()
Meth : get_IsSynchronized()
Meth : get_SyncRoot()
Meth : CopyTo(
array : System.Array
index : System.Int32
)
Meth : get_IsFixedSize()
Meth : get_IsReadOnly()
Meth : Clone()
Meth : GetHashCode()
Meth : Equals(
obj : System.Object
)
Meth : ToString()
Meth : CreateInstance(
elementType : System.Type
length : System.Int32
)
...
Для
того чтобы получить доступ к сборке (в нашем примере мы использовали
сборку по умолчанию (— mscorlib.dll), всегда загруженную в память),
надо обратиться к этой сборке. Вот как это сделать:
Imports System.Reflection
Imports System.IO
Imports Microsoft.Win32
Imports Microsoft.VisualBasic
Module Module1
Sub Main()
Dim Asm As [Assembly]
Dim Mdls As [Module]()
Dim Mdl As [Module]
Asm = [Assembly].LoadFrom(GetNetFrameworkPath() + _
"system.windows.forms.dll")
Mdls = Asm.GetModules
Mdl = Mdls(0)
End Sub
Function GetNetFrameworkPath() As String
Dim Key As RegistryKey = _
Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\.NETFramework")
GetNetFrameworkPath = CType(Key.GetValue("InstallRoot"), String) + _
CType(Key.GetValue("Version"), String) + "\"
End Function
End Module
После
того как мы получили доступ к модулю, мы можем либо изучить определенные
в нем типы (как это сделать, показано в первом примере), либо получить
информацию об интересующем нам типе.
В
следующем номере мы продолжим знакомство с библиотекой классов .NET
Framework Class Library. Мы рассмотрим массивы (класс System.Array)
и коллекции (пространство имен System.Collections).
|