Знакомство с Microsoft .NET Framework

Часть 3. Библиотека классов

Алексей Федоров

Класс 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).

КомпьютерПресс 2'2002