Симон Робинсон - C# для профессионалов. Том II
Хотя средства позднего связывания C# позволяют избежать трудностей RCW, необходимо знать о некоторых, связанных с этим, недостатках.
Первый: позднее связывание может быть опасным. При использовании раннего связывания компилятор может запросить библиотеку типов компонента COM, чтобы убедиться, что все вызываемые на объектах COM методы в действительности существуют. При позднем связывании ничто не препятствует опечатке в вызове метода InvokeMember(), что может породить ошибку во время выполнения.
Второй: позднее связывание может быть медленным. Каждый раз при использовании InvokeMember() на объектной ссылке среда времени выполнения должна найти требуемый член в библиотеке функций класса COM. Это приводит к снижению производительности программы.
Третий: написание кода с поздним связыванием может оказаться трудоемким. Так как не требуется ссылаться на библиотеку типов компонента COM, IDE VS.NET не может использовать Intellisense, чтобы помочь с именами членов и списками аргументов, поэтому в коде могут появиться ошибки, которые будет трудно найти до времени выполнения.
Использование элементов управления ActiveX в .NET
Элемент управления ActiveX является частным типом компонента COM, который поддерживает специальное множество интерфейсов для обеспечения графического представления. Также, как можно импортировать стандартные компоненты COM для использования в проектах .NET, можно также импортировать элементы управления ActiveX. Это позволяет сделать утилита AxImp.exe.
AxImp.exe
Чтобы импортировать компонент ActiveX в среду .NET, утилита AxImp.exe вызывается из командной строки. Команда состоит из двух частей:
1. Имени AxImp.
2. Абсолютного или относительного пути доступа к файлу ActiveX (*.осх), который должен быть импортирован.
Для примера рассмотрим снимок экрана, приведенный ниже. Здесь импортируется элемент управления ActiveX Win32 MAPI и определяется расположение файла .осх (C:windowssystemmsmapi32.осх):
Как можно видеть, программа AxImp.exe выводит два файла.
Первый выходной файл MSMAPI.dll является прокси для сборки. Он позволяет ссылаться на компонент ActiveX, как если бы это был неграфический объект, с помощью его методов и свойств таким же образом, каким используются методы и свойства неграфического класса.
Второй файл AxMSMAPI.dll является элементом управления Windows. Он позволяет использовать графический аспект импортированного элемента управления ActiveX как элемент управления Windows в проектах Forms Windows .NET.
При использовании AxImp желательно убедиться, что для этих двух выходных файлов предоставляются явные и уникальные имена, так как, по крайней мере, в бета-версии SDK .NET AxImp.exe имеет потенциальную возможность перезаписывать входные файлы без предупреждения.
Ссылка на сборку прокси ActiveX
Как сказано выше, вывод сборки прокси утилитой AxImp.exe позволяет ссылаться на компонент ActiveX программным путем без использования графических аспектов. Для этого необходимо просто добавить ссылку на прокси сборки с помощью вкладки Reference в IDE VS.NET после того, как AxImp.exe сделает свою работу:
После создания ссылки на сборку прокси можно использовать в коде программы компонент ActiveX. В примере ниже используется прокси MSMAPI32.осх для отправки почтового сообщения:
public static int Main() {
MAPISession objSession=new MAPISession();
MAPIMessages objMessage=new MAPIMessages();
objSession.Password="password";
objSession.UserName=" [email protected]";
objSession.SignOn();
objMessage.SessionID=objSession.SessionID;
objMessage.Compose();
objMessage.MsgSubject="MAPI Contol Test";
objMessage.MsgNoteText="The message body.";
objMessage.RecipAddress=" [email protected]";
objMessage.ResolveName();
objMessage.Send(null);
objSession.SignOff();
return 0;
}
Размещение элемента управления ActiveX в WinForm
Также достаточно просто разместить элемент управления ActiveX в форме Windows. Чтобы сделать это, сначала запустим диалоговое окно Customize Toolbox из IDE VS.NET, щелкнув правой кнопкой мыши в панели инструментов IDE и выбрав соответствующий пункт в контекстном меню. Когда появится диалоговое окно, надо перейти на вкладку .NET Framework Components и найти созданный утилитой AxImp.exe файл элемента управления Windows. После закрытия диалогового окна Customize Toolbox импортированный элемент управления появится в панели управления IDE и можно будет добавить его в Windows Form таким же образом, каким добавляются любые другие элементы управления Windows.
Использование компонентов .NET в COM
Также, как используются компоненты COM и элементы управления ActiveX в коде .NET, можно применять компоненты .NET в стандартном коде Windows. Только несколько свойств сборок .NET недоступны через COM, включая параметризованные конструкторы, статические методы и константные поля. Кроме того, доступ к перегруженным методам .NET из COM требует дополнительной работы.
RegAsm.exe
Применение компонентов COM в коде .NET требует другой утилиты, которая существует в SDK .NET, являющейся аналогом программы импорта библиотеки типов, которую мы видели ранее. Название этой утилиты — RegAsm.exe.
Название утилиты RegAsm (Register Assembly) обозначает ее функцию, она отвечает за ввод информации о типе компонента .NET в системный реестр, чтобы службы COM могли к нему обратиться. После регистрации компонента .NET с помощью RegAsm, стандартные клиенты Windows могут сделать позднее соединение с классами компонента. Процесс регистрации компонента должен быть сделан только один раз. После регистрации все клиенты COM могут к нему обращаться.
В качестве примера рассмотрим следующий код. Он принадлежит классу в библиотеке классов .NET. Функция получает просто число в качестве аргумента ввода и возвращает факториал этого числа:
namespace Factorial {
using System;
public class Factorial {
// Этот метод вычисляет факториал числа
public int ComputeFactorial(int n) {
int intFactorial=n;
for (int i = 1; i<n; i++) {
intFactorial*=i;
}
return intFactorial;
}
}
}
После компиляции класса примера в сборку .NET можно зарегистрировать эту сборку в службах COM с помощью RegAsm.exe:
Теперь, когда сборка зарегистрирована в службах COM с помощью RegAsm, можно выполнить позднее связывание со сборкой .NET через службы COM. С целью демонстрации создадим простой сценарий VB, который это делает. (Сценарий VB можно создать с помощью текстового редактора, такого как Notepad; введите просто следующий код и сохраните файл с расширением .vbs. Предполагая, что Windows Script Host установлен, файл при вызове будет выполняться как сценарий. Помните, что сценарий VB выполняет позднее связывание для компонентов COM.)
Option Explicit
Dim objFactorial
Dim lngResult
Dim lngInputValue
Set objFactorial=CreateObject("Factorial.Factorial")
lngInputValue=InputBox("Numbers?")
IngResult=objFactorial.ComputeFactorial(CLng(lngInputValue))
Call MsgBox(lngResult)
Однако, прежде чем это можно будет использовать, необходимо установить сборку в глобальный кэш. Для этого сначала создадим устойчивое имя сборки с помощью следующей команды:
sn -k Factorial.dll
Далее необходимо создать файл AssemblyInfo.cs со следующим содержимым:
using System.Reflection;
[assembly: AssemblyKeyFile("factorial.snk")]
Затем это надо откомпилировать с помощью следующей команды, чтобы превратить в модуль:
CSC /t:module /out: AssemblyInfo.dll AssemblyInfo.cs
После этого компилируется файл Factorial.cs, и полученная DLL устанавливается в глобальный кэш с помощью gacutil следующим образом:
csc /t:library /addmodule:assemblyinfо.dll Factorial.cs gacutil /i Factorial.dll
При выполнении сценарий VB воспользуется службами COM для создания объекта .NET, вызовет метод на этом объекте и выведет возвращаемое из объекта .NET значение в окне сообщения:
Интересная техника, не правда ли? Но она не решает ни одной из упомянутых выше проблем, связанных с поздним связыванием. К счастью, другой член набора инструментов SDK .NET может в этом помочь. Это утилита TlbExp.exe.
Однако, прежде чем попрощаться с TlbImp.exe, необходимо запомнить одну вещь: службы COM должны иметь возможность найти компонент сборки .NET, когда он вызывается. Это означает, что сборка должна располагаться в рабочей папке клиента или в глобальном коде сборки системы.
TlbExp.exe
TlbExp обозначает Type Library Exporter (экспортер библиотеки типов). При выполнении на файле сборки .NET TlbExp может запросить внутренний манифест этой сборки и вывести соответствующий файл библиотеки типов COM (*.tlb). Когда TlbExp создаст файл библиотеки типов для компонента .NET, языки разработки не принадлежащие .NET, такие как VB6, смогут ссылаться на него, используя для того, чтобы получить эффективное раннее связывание с компонентами .NET: