| СТАТЬЯ | 13.05.02 | 
Знакомство с Microsoft 
    .NET Framework
    Часть 3. Библиотека классов
© Алексей Федоров
  Материал опубликован в КомпьютерПресс 
  №1'2002
В двух предыдущих частях данной статьи мы начали знакомство с Microsoft .NET Framework — ключевым компонентом Microsoft .NET, представляющим собой платформу для создания, внедрения и выполнения Web-сервисов и приложений. Мы рассказали об основных компонентах Microsoft .NET Framework и кратко описали их назначение. Мы также начали более подробное рассмотрение Common Language Runtime (CLR) — среды выполнения .NET-приложений. Завершили мы знакомство с Common Language Runtime рассказом о Common Type System.
В этом номере мы начнем знакомство с библиотекой классов, рассмотрим основные составляющие ее пространства имен и классы и приведем некоторые примеры их использования.
Библиотека классов .NET Framework Class Library содержит классы, обеспечивающие следующие функции:
Все классы, реализованные в .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 является корневым пространством имен в Microsoft .NET Class Library и содержит фундаментальные типы данных, реализованные в .NET Framework. Это пространство имен содержит класс Object, который служит предком для всех классов в библиотеке классов .NET, примитивные и расширенные типы, а также более 100 дополнительных классов, используемых для обработки исключительных ситуаций, управления доменами приложений, сборки мусора и т.п.
Класс System.Object служит предком для всех классов в библиотеке классов .NET. Методы, реализованные в данном классе, показаны на следующем рисунке.
Кратко рассмотрим каждый из этих методов:
Ниже мы расскажем, как используется класс 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, а затем проиллюстрируем некоторые из них примерами. 
В следующем примере показано, как получить список типов, определенных в данном модуле.
'------------------------------------------- 
  ' .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 
                 
                 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).
Дополнительная информация
Дополнительную информацию Вы можете получить в компании Interface Ltd.
Обсудить на форуме 
  Microsoft
  Отправить 
  ссылку на страницу по e-mail 
| Interface Ltd. Отправить E-Mail http://www.interface.ru | |
| Ваши 
      замечания и предложения отправляйте 
      автору По техническим вопросам обращайтесь к вебмастеру Документ опубликован: 13.05.02 |