Книга: C# для профессионалов. Том II
Позднее связывание с компонентами COM
Позднее связывание с компонентами COM
Прежде чем исполнимый файл клиента сможет вызвать методы и свойства объекта компонента, ему необходимо узнать адреса памяти этих методов и свойств. Существуют две различные технологии, которые клиентские программы могут использовать для определения этих адресов.
Программы с ранним связыванием узнают адреса на ранней стадии процесса компиляции/выполнения — во время компиляции. Когда программа (ранним связыванием компилируется, компилятор использует библиотеку типов компонента для включения адресов методов и свойств компонента в клиентскую исполнимую программу, чтобы к адресам можно было очень быстро и безошибочно обращаться. Технологии взаимодействия COM которые были рассмотрены до сих пор, используют раннее связывание.
Со своей стороны, программы с поздним связыванием узнают адреса свойств и методов на поздней стадии процесса компиляции/выполнения, в тот самый момент, когда эти свойства и методы вызываются. Код с поздним связыванием обычно обращается к клиентским объектам через базовые типы данных, такие как object
, и использует среду времени выполнения для динамического определения адресов методов. Хотя код с поздним связыванием позволяет использовать некоторые сложные технологии программирования, такие как полиморфизм, он требует некоторых связанных расходов, которые мы вскоре увидим.
Но сначала проверим, как позднее связывание выполняется с помощью отражения в C# (Отражение, является способом, который используется кодом во время выполнения для определения информации об интерфейсах серверных классов; см. главу 5.)
При позднем связывании с объектом COM в программе C# не нужно создавать RCW для компонента COM. Вместо этого вызывается метод класса GetTypeFromProgID
класса Type для создания экземпляра объекта, представляющего тип объекта COM. Класс Type
является членом пространства имен System.Runtime.InteropServices
и в коде ниже мы конфигурируем объект Type
для того же компонента COM доступа к данным, который использовался в предыдущих примерах:
using System.Runtime.InteropServices;
Type objCustomerTableType;
objCustomerTableType = Type.GetTypeFromProgID("DataAccess.CustomerTable");
Когда имеется объект Type
, инкапсулирующий информацию о типе объекта COM, он используется для создания экземпляра самого объекта COM. Это реализуется передачей объекта Type
в метод класса CreateInstance
класса Activator.CreateInstance
создает экземпляр объекта COM и возвращает на него ссылку позднего связывания, которую можно сохранить в ссылке типа object.
object objCustomerTable;
objCustomerTable = Activator.CreateInstance(objCustomerTableType);
В этом месте код C# имеет ссылку позднего связывания на готовый экземпляр класса COM.
К сожалению, невозможно вызывать методы непосредственно на ссылке типа object
. Чтобы можно было обратиться к объекту COM, необходимо использовать метод InvokeMember
объекта Type
, который был создан вначале. При вызове метода InvokeMember
ему передается ссылка на объект COM вместе с именем вызываемого метода COM, а также массив типа object
всех входящих аргументов метода.
ObjCustomerTableType.InvokeMember("Delete", BindingFlags.InvokeMethod, null, objCustomerTable, aryInputArgs);
Напомним еще раз последовательность действий:
1. Создать объект Type
для типа объекта COM с помощью метода класса Type.GetTypeFromProgID()
.
2. Использовать этот объект Type
для создания объекта COM с помощью Activator.CreateInstance()
.
3. Методы вызываются на объекте COM, вызывая метод InvokeMember
на объекте Type
и передавая в него ссылку object
в качестве входящего аргумента. Ниже приведен пример кода, объединяющий все это в один блок:
using System.Runtime.InteropServices;
Type objCustomerTableType;
object objCustomerTable;
objCustomerTableType=Type.GetTypeFromProgID("DataAccess.CustomerTable");
objCustomerTable=Activator.CreateInstance(ObjCustomerTableType);
objCustomerTableType.InvokeMember("Delete", BindingFlags, InvokeMethod, null, objCustomerTable, aryInputArgs);
objCustomerTableType = Type.GetTypeFromProgID("DataAccess.CustomerTable");
Хотя средства позднего связывания C# позволяют избежать трудностей RCW, необходимо знать о некоторых, связанных с этим, недостатках.
Первый: позднее связывание может быть опасным. При использовании раннего связывания компилятор может запросить библиотеку типов компонента COM, чтобы убедиться, что все вызываемые на объектах COM методы в действительности существуют. При позднем связывании ничто не препятствует опечатке в вызове метода InvokeMember()
, что может породить ошибку во время выполнения.
Второй: позднее связывание может быть медленным. Каждый раз при использовании InvokeMember()
на объектной ссылке среда времени выполнения должна найти требуемый член в библиотеке функций класса COM. Это приводит к снижению производительности программы.
Третий: написание кода с поздним связыванием может оказаться трудоемким. Так как не требуется ссылаться на библиотеку типов компонента COM, IDE VS.NET не может использовать Intellisense, чтобы помочь с именами членов и списками аргументов, поэтому в коде могут появиться ошибки, которые будет трудно найти до времени выполнения.
- Chapter 16. Commercial products based on Linux, iptables and netfilter
- Appendix A. Detailed explanations of special commands
- Appendix B. Common problems and questions
- SCTP Common and generic headers
- SCTP SHUTDOWN COMPLETE chunk
- Compiling the user-land applications
- Complex protocols and connection tracking
- Basics of the iptables command
- Commands
- Comment match
- What Goes Around Comes Around
- Папка «Мой компьютер» (MyComputer)