Пример. Создание компонента с помощью Visual Basic
Компоненты хранят код, доступный для многократного использования, в форме объектов. Приложение, использующее код компонента (создавая объекты и вызывая их свойства и методы), называется клиентом. Клиент не обязательно должен находиться в той же сборке, что и используемый им компонент.
Следующие процедуры построены на основе друг друга, поэтому важно выполнять их именно в том порядке, в котором они приведены.
Примечание
Отображаемые диалоговые окна и команды меню могут отличаться от описанных в справке в зависимости от текущих настроек или выпуска.Чтобы изменить параметры, выберите в меню Сервис пункт Импорт и экспорт параметров.Дополнительные сведения см. в разделе Работа с параметрами.
Создание проекта
Чтобы создать библиотеку классов CDemoLib и компонент CDemo
В меню Файл выберите Создать и щелкните пункт Проект, чтобы открыть диалоговое окно Создание проекта. Из списка типов проектов Visual Basic выберите шаблон проекта Библиотека классов и введите CDemoLib в поле Имя.
Примечание
Для создаваемого проекта следует всегда задавать имя.Это гарантирует, что будет задано корневое пространство имен, имя сборки и имя проекта, а компонент, создаваемый по умолчанию, будет помещен в правильное пространство имен.
В обозревателе решений щелкните правой кнопкой мыши CDemoLib и выберите в контекстном меню Свойства. Обратите внимание, что в поле Корневое пространство имен появился элемент CDemoLib.
Для определения имен компонентов в сборке используется корневое пространство имен. Например, если в двух сборках содержатся компоненты с именем CDemo, то можно указать свой компонент CDemo, используя имя CDemoLib.CDemo.
Закройте диалоговое окно.
В меню Проект выберите Добавить компонент. В диалоговом окне Добавление нового элемента выберите Класс компонента и введите CDemo.vb. в поле Имя. В результате в библиотеку классов добавляется компонент CDemo.
Нажмите кнопку Показать все файлы в обозревателе решений. Откройте узел CDemo.vb для отображения файла CDemo.Designer.vb. Щелкните правой кнопкой мыши CDemo.Designer.vb и выберите из контекстного меню Просмотреть код. Открывается редактор кода.
Обратите внимание на Inherits System.ComponentModel.Component непосредственно под Partial Public Class CDemo. В этом разделе задается класс, от которого наследует создаваемый класс. По умолчанию компонент является наследником класса Component, предоставляемого системой. Класс Component предоставляет компоненту различные возможности, в частности способность использовать конструкторы.
Найдите Public Sub New(). Выделите полностью тело метода и вырежьте его из файла CDemo.Designer.vb, нажав CTRL-X.
В обозревателе решений щелкните правой кнопкой мыши CDemo.vb и выберите из контекстного меню Просмотреть код. Открывается редактор кода.
Вставьте выделенный фрагмент в тело класса CDemo. Это позволяет работать с новыми элементами без вмешательства проектировщика.
В обозревателе решений щелкните правой кнопкой мыши Class1.vb и выберите Удалить. В результате класс, предоставляемый библиотекой классов и используемый по умолчанию, удаляется (он не будет использоваться в этом пошаговом руководстве).
Из меню Файл выберите команду Сохранить все, чтобы сохранить проект.
Добавление конструкторов и методов завершения
Конструкторы управляют инициализацией компонента, а метод Finalize — его удалением. Код конструктора и метода Finalize класса CDemo поддерживает определение числа существующих объектов CDemo.
Чтобы добавить код для конструктора и метода завершения класса CDemo
В Редакторе кода добавьте переменные-члены для хранения общего числа экземпляров класса CDemo и идентификатора каждого экземпляра.
Public ReadOnly InstanceID As Integer Private Shared NextInstanceID As Integer = 0 Private Shared ClassInstanceCount As Long = 0
Поскольку переменные-члены InstanceCount и NextInstanceID объявлены как Shared, они существуют только на уровне класса. Все экземпляры объекта CDemo, обращающиеся к этим членам, используют один и тот же адрес в памяти. Общие члены инициализируются при первом обращении к классу CDemo в коде (например, при первом создании объекта CDemo или при первом обращении к одному из общих членов класса).
Найдите Public Sub New() и Public Sub New(Container As System.ComponentModel.IContainer), констурктор по умолчанию для класса CDemo. В Visual Basic все конструкторы называются New. У компонента может быть несколько конструкторов, каждый со своими параметрами, но все они должны называться New.
Примечание
Уровень доступа конструктора определяет, какие клиенты могут создавать экземпляры класса.В других версиях Visual Basic создание объектов управлялось свойством Instancing. Если было использовано свойство Instancing, рекомендуется прочесть раздел Изменения в создании экземпляров компонентов в Visual Basic.
Добавьте в процедуру Sub New() следующий код, увеличивающий счетчик экземпляров при создании нового экземпляра класса CDemo и задающий идентификатор экземпляра.
Примечание
Всегда добавляйте код после вызова метода InitializeComponent.На этом этапе все необходимые компоненты инициализированы.
InstanceID = NextInstanceID NextInstanceID += 1 ClassInstanceCount += 1
Для членов с разрешением ReadOnly значение InstanceID можно задавать только в конструкторе..
Примечание
Пользователи, знакомые с многопоточностью, могут справедливо отметить, что назначение значения InstanceID и увеличение значения NextInstanceID должно быть неделимой операцией.Этот, а также другие вопросы, связанные с многопоточностью, освещено в разделе Пошаговое руководство. Разработка простого многопоточного компонента с использованием Visual Basic.
Добавьте в конец конструктора следующий метод:
Protected Overrides Sub Finalize() ClassInstanceCount -= 1 End Sub
Диспетчер памяти вызывает Finalize непосредственно перед освобождением памяти, занимаемой объектом CDemo. Метод Finalize первоначально определяется с типом Object, корневым типом для всех ссылочных типов в иерархии классов .NET. При переопределении метода Finalize можно выполнять операции очистки ресурсов непосредственно перед удалением компонента из памяти. Однако, как будет показано далее в этом пошаговом руководстве, существуют веские аргументы в пользу более раннего освобождения ресурсов.
Добавление свойства в класс
У класса CDemo есть только одно свойство. Это общее свойство, позволяющее клиенту узнать число объектов CDemo в памяти на данный момент. Методы создаются аналогичным образом.
Чтобы создать свойство для класса CDemo
Добавьте в класс CDemo следующее объявление свойства, позволяющее клиентам узнать число экземпляров класса CDemo.
Public Shared ReadOnly Property InstanceCount() As Long Get Return ClassInstanceCount End Get End Property
Примечание
Синтаксис объявления свойства отличается от синтаксиса в предыдущих версиях Visual Basic.Дополнительные сведения об изменении синтаксиса см. в разделе Property Procedure Changes for Visual Basic 6.0 Users.
Тестирование компонента
Чтобы протестировать компонент, необходим проект, в котором он используется. Этот проект должен запускаться первым при нажатии кнопки Выполнить.
Чтобы добавить клиентский проект CDemoTest в качестве автозагружаемого проекта для решения
В меню Файл наведите указатель мыши на Добавить и выберите Создать проект, после чего открывается диалоговое окно Добавление нового проекта.
Выберите шаблон проекта Приложение Windows и введите CDemoTest в поле Имя, а затем щелкните ОК.
В обозревателе решений щелкните правой кнопкой мыши CDemoTest, а затем из контекстного меню выберите Назначить автозагружаемым проектом.
Чтобы клиентский тестовый проект мог использовать компонент CDemo, он должен ссылаться на проект библиотеки классов. После добавления ссылки следует добавить в тестовое приложение оператор Imports, чтобы облегчить использование компонента.
Добавление ссылки на проект библиотеки классов
Нажмите кнопку Показать все файлы в обозревателе решений. Щелкните правой кнопкой мыши узел Ссылки, расположенный непосредственно под CDemoTest, и выберите из контекстного меню команду Добавить ссылку.
В диалоговом окне Добавить ссылку перейдите на вкладку Проекты.
Дважды щелкните проект библиотеки классов CDemoLib. Под узлом Ссылки проекта CDemoTest появляется строка CDemoLib.
В обозревателе решений щелкните правой кнопкой мыши Form1.vb и выберите из контекстного меню Просмотреть код.
Добавление ссылки на CDemoLib позволяет использовать полное имя компонента CDemo, т.е. CDemoLib.CDemo.
Чтобы добавить оператор "Imports"
Добавьте следующий оператор Imports в верхней части Редактора кода для Form1 над объявлением Class:
Imports CDemoLib
Оператор Imports позволяет опускать имя библиотеки и ссылаться на тип компонента по имени CDemo. Дополнительные сведения об операторе Imports см. в разделе Пространства имен в Visual Basic.
Далее будет создана тестовая программа для проверки компонента.
Основные сведения о времени жизни объекта
В программе CDemoTest демонстрируется время жизни объектов в .NET Framework. Для этого создается и освобождается большое число объектов CDemo.
Чтобы добавить код для создания и освобождения объектов CDemo
Щелкните Form1.vb[Design], чтобы вернуться в конструктор.
Перетащите Button и Timer с вкладки Все формы Windows Forms на Панели элементов на поверхность разработки Form1.
Невизуальный компонент Timer отображается на отдельной поверхности разработки ниже формы.
Дважды щелкните значок Timer1, чтобы создать метод обработки событий для события Tick компонента Timer1. Поместите в этот метод обработки событий следующий код:
Me.Text = "CDemo instances: " & CDemo.InstanceCount
По истечении каждого кванта времени таймера в подписи формы отображается текущее число экземпляров класса CDemo. В качестве квалификатора для общего свойства InstanceCount используется имя класса. Для обращения к общему члену не требуется создавать экземпляр CDemo.
Щелкните вкладку Form1.vb[Design], чтобы вернуться в конструктор.
Щелкните правой кнопкой мыши Timer1 и из контекстного меню выберите Свойства. В окне Cвойства присвойте свойству Enabled значение True. Это позволяет запустить таймер сразу после создания формы.
Дважды щелкните Button в форме Form1, чтобы создать метод обработки событий для события Click этой кнопки. Поместите в этот метод обработки событий следующий код:
Dim cd As CDemo Dim ct As Integer For ct = 1 To 1000 cd = New CDemo Next
Этот код может показаться странным. При каждом создании экземпляра CDemo предыдущий экземпляр освобождается. После окончания цикла For остается только один экземпляр CDemo. После выхода из метода обработки событий освобождается и этот экземпляр, так как переменная cd выходит за область действия.
Однако уже понятно, что дело обстоит не совсем так.
Чтобы запустить и выполнить отладку проектов CDemoTest и CDemo
Нажмите клавишу F5, чтобы запустить решение.
Запускается клиентский проект, и на экране отображается форма Form1. Обратите внимание, что в заголовке формы отображается "CDemo instances: 0".
Нажмите кнопку. В заголовке формы должна отображаться надпись "CDemo instances: 1000".
Все экземпляры CDemo были освобождены на момент завершения процедуры обработки события Click этой кнопки. Но почему тогда они не были завершены? Если не углубляться в детали, то диспетчер памяти завершает объекты в фоновом режиме с низким приоритетом. Этот приоритет повышается лишь в том случае, когда в системе не хватает свободной памяти. Эта схема отложенного сбора мусора позволяет очень быстро выделять память под объекты.
Нажмите эту кнопку еще несколько раз, следя за подписью формы. В некоторый момент число экземпляров внезапно резко снижается. Это означает, что диспетчер памяти освободил память, занимаемую ранее некоторыми из этих объектов.
Примечание
Если кнопка была нажата более 10 раз, а число экземпляров CDemo не уменьшилось, возможно, потребуется изменить код таким образом, чтобы он использовал больший объем памяти.Закройте форму, чтобы вернуться в среду разработки, и увеличьте число итераций цикла For до 10000.Затем снова запустите проект.
Повторите шаг 3. После этого система сможет создать больше объектов, прежде чем диспетчер памяти начнет завершать их.
Фактически, каждое повторение шага 3 позволяет выделять больше объектов CDemo до того, как диспетчер памяти начнет свою работу. Это объясняется тем, что все больше компонентов Visual Studio выгружается, и для экземпляров CDemo остается больше пространства.
Закройте форму, чтобы вернуться в среду разработки.