Книга: 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, чтобы помочь с именами членов и списками аргументов, поэтому в коде могут появиться ошибки, которые будет трудно найти до времени выполнения.

Оглавление книги


Генерация: 1.746. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз