Поиск по блогу

Thursday, January 3, 2008


Использование Automation (ActiveX/Com) объектов в ASP.NET 1)

Иногда мы склонны полагать, что .NET является панацеей от всех наших проблем и что все технологии, используемые до наступления эры .NET должны быть немедленно отправлены в Корзину. Технология, которая в значительной степени страдает от этого непонимания, - ActiveX, также известная как (OLE) или automation COM. Функция CreateObject функция создает COM-объекты и часто используется в классических серверных ASP скриптах для настройки веб-страниц. Это не всегда является наилучшим методом кодирования, но оно работает. Серверные элементы управления ASP.NET и действительно объектно-ориентированный .NET Framework - это огромный шаг вперед. Для решения многих проблем, для которых раньше применялась COM сейчас лучше использовать .NET, но это не означает, что COM больше не существует. Если некоторые из ваших существующих COM классов работают хорошо, то почему вы должны конвертировать их в .NET? Это не то, что COM обещала Вам! Расслабьтесь, существует еще много вещей, которые можно делать при помощи COM в ASP.NET. В этой статье я покажу вам некоторые из достоинств COM, которые она может вам предложить.

COM-ы не вымерли!

Прежде чем погрузиться в .NET разработку я хочу ближе познакомить вас с COM. COM расшифровывается как Объектная Модель Компонентов, которая описывает протокол, разделяющий интерфейс объекта и его реализацию. Интерфейс - это то, как объект выглядит, это декларация его свойств и методов. Реализация - это код, который фактически исполняется, когда метод вызывается или читаются свойства. Пользователь объекта использует COM, чтобы получить описание класса и, таким образом, построить объект этого класса. Пользователь получает COM-интерфейс к объекту. Все методы и свойства могут быть выполнены через этот интерфейс, но сам COM-объект не может быть уничтожен пользователем. COM-объект будет удален сборщиком мусора. Здесь нет ничего необычного, интерфейсы широко используются в .NET. Описание классов это одно из достоинств .NET и в каждой сборке присутствует в виде метаданных. В COM используются библиотеки типов (typelibraries) для описания классов, они довольно часто доступны как ресурсы внутри самого файла библиотеки.

Windows поддерживает множество типов COM-интерфейсов, наиболее часто используемый - это IDispatch интерфейс. В реализации COM-класса этого интерфейса его функционал поддерживает два метода:

  1. Его методы можно вызвать прямо из виртуальной таблицы (vtable) объекта, формат vtable описан в typelibrary этого COM-класса. Компилятор перенаправляет вызовы согласно vtable. Это называется vtable-связыванием, или как говорят сегодня ранним связыванием. (Фактически раннее связывание ссылается на диспетчерские интерфейсы (dispinterfaces), область действия которых ограничена событиями COM).

  2. В интерфейсе есть методы, принимающие название метода или свойства в строковом формате, выполняющие динамический поиск в typelibrary, после чего метод может быть вызван. Интерпретатор скрипта использует эти методы для перенаправления вызовов скрипта методам объекта. Это называется поздним связыванием.

Классические ASP-скрипты используют второй метод для заполнения веб-страниц на сервере. Клиентские скрипты используют позднее связывание для исполнения кода в браузере клиента. Объекты, к которым обращаются с помощью этих IDispatch интерфейсов, часто называют как (OLE) automation объекты. Термин ActiveX когда-то придуманный для всего COM функционала сегодня в основном используется для описания визуальных (ActiveX) элементов управления, к которым обращаются с помощью целого набора различных COM-интерфейсов.

COM идеальный протокол для подключения компонент, созданных с помощью различных средств, он поддерживается всеми основными Windows-языками, например, VB (A), Delphi, C++, VBscript и JavaScript и конечно-же в .NET. В библиотеке классов .NET вы найдете пространство имен System.runtime.interop. Большинство свойств и методов оттуда отвечают за неуправляемые COM-соединения, которые предусматривают создание COM-объектов, а также за передачу данных между этими объектами. COM-объекты не работают в безопасном типе управляемого .NET-кода. Связь между управляемой и неуправляемой частью вполне работоспособна. Распределение данных также называется сортировкой, .NET будет использовать собственный системный сортировщик для сортировки COM-объектов. Иногда можно услышать, что части .NET реализованы с помощью COM. Я бы сказал, что COM и .NET используют одни и те же методы для соединения объектов.

Начнем работу с COM в ASP.NET приложениях. Я построил очень простой automation-сервер. Она называется DemoServer.MyDemo, и он поддерживает один метод, названный MyMethod, принимающий один параметр типа строка и возвращающий эту же строку с префиксом "your server echoes ". Он сделан на Delphi, более подробно о том как это сделать Вы можете найти на www.Gekko-Software.nl/Software.htm

Клиентские Automation-объекты

В ASP.NET приложениях весь код исполняется на IIS-сервере. Код, работающий у клиента может выполнять отдельные функции, такие как проверку наличия какого-либо устройства или открытие пользователем адресной книги и отправку данных на серверную часть приложения. В случае реализации в качестве automation сервера, объекты просматриваемой страницы можно создавать и управлять ими с помощью небольших фрагментов сценария. Поскольку я не очень хорошо знаком с html, я предпочитаю реализовывать все это на C# с веб-страницей с раздельным кодом.

Я буду экспериментировать с простой веб-страницей. Эта страница имеет два элемента TextBox и Button. Это все серверные элементы управления, что означает, что они недоступны на клиентской машине так же как на сервере. TextBox-ы в клиентской форме будут представлены в виде текстового поля ввода. Мой скрипт может считывать и устанавливать их текстовые значения, которые будут доступны на сервере после отправки данных. Первый TextBox используется для ввода строки, которая будет передана automation-объекту, второй TextBox содержит результат вызова функции объекта. Я напишу Jscript функцию, которая создает automation-объект, читает TextBox, взывает метод и обновляет второй TextBox.

function doMySubMit() {

var MyAx;

MyAx = new ActiveXObject("DemoServer.MyDemo");

document.getElementById('TextBox2').value = MyAx.MyMethod(document.getElementById('TextBox1').value);

}


ActiveXObject это Jscript-функция, которая создает новый automation (ActiveX) объект, идентифицируемый с помощью ProgId параметра. В полученном в результате объекте я вызываю MyMethod, передавая ему строку из TextBox1. Результат заносится в TextBox2.

В C # константы будут храниться в классах, как собственно и все остальное. Я создам статический класс, содержащий текст сценария и соответствующие константы:

class MyJScript {
const string
head = "<script language="JavaScript">";
const string
foot = "</script>";
public const string
scriptBlockName = "startup";
public const string
functionName = "doMySubMit()";
public const string
MySubmit =
head +
"function " + functionName + "{" +
"var MyAx;" +
"MyAx = new ActiveXObject("DemoServer.MyDemo");" +
"document.getElementById('TextBox2').value = MyAx.MyMethod(document.getElementById('TextBox1').value);" +
"}" +
foot;
}


Статические классы можно использовать, не создавая объекта. После объявления я могу использовать MyJscript.MySubmit, - константу, содержащую JavaScript-код заключенный теги скрипта.

В событии Page_Load я могу приспособить страницу для своих нужд. Помимо установки контролов, я могу добавить здесь клиентские скрипты. Page.RegisterStartupScript вставляет блок скрипта на страницу. Перед этим Page.IsStartupScriptRegistered проверяет, был ли скрипт уже добавлен на страницу для предотвращения двойной работы. Page.RegisterOnSubmitStatement является гораздо более мощным методом, в котором я могу определить имя функции клиентского скрипта (из моего только-что вставленного блока скрипта), который будет вызываться при отправке формы на сервер. Класс MyJScript предоставляет все параметры, необходимые для этих методов.

private void Page_Load(object sender, System.EventArgs e)

{

// Put user code to initialize the page here

if (! IsStartupScriptRegistered(MyJScript.scriptBlockName))

RegisterStartupScript(MyJScript.scriptBlockName, MyJScript.MySubmit);

RegisterOnSubmitStatement("Mysubmit", MyJScript.functionName);

}


Когда страница отправляется на сервер, на клиенте запускается моя Jscript функция, убедиться в ее работе можно проверив TextBox2. Internet Explorer выдаст предупреждение, что данный код является потенциально опасным. Automation-объекты могут содержать в себе код, которые мог бы изменить, например, пользовательскую адресную книгу или даже отформатировать диски. Если настройки безопасности IE, не слишком низкие, будет выдаваться диалоговое окно с предупреждением.

Чтобы предотвратить появление это окна можно либо изменить настройки безопасности браузера либо подписать ваш ActiveX класс. Первый вариант не следует воспринимать слишком серьезно. Во втором случае вы в конечном итоге приобретете сертификат у такой компании как Verisign, которым можно подписывать ваши automation-классы как надежные. Подписание совсем несложно в .NET, но и для классических automation-классов оно требует достаточно времени и денег.

Серверные Automation-объекты

Большинство классических ASP скриптов выполняются на сервере. Automation-объекты, используемые скриптах выполняют работу (или часть ее) лучше, так как выполнены лучше и по более надежным технологиям. Неизбежные ошибки сценария выявляются слишком поздно, потому что многие ошибки незаметны до тех пор, пока сценарий не начал работать. Кроме того, cкомпилированный код работает быстрее интерпретируемого. С ASP.NET этот "ад сценариев" может быть отправлен в корзину и от многих automation-объектов, которые только генерируют html-код можно с успехом отказаться. Зато остальные automation-классы все еще остаются полезными. Первый вариант состоит в том, чтобы переделать их в .NET, а другой - использования их как есть. Благодаря поддержки automation в .NET последнее несложно сделать.

В solution explorer-е я добавлю ссылку на библиотеку COM, которую я хочу использовать. После нажатия кнопки "Добавить ссылку", в solution explorer-е я щелкаю ярлычок COM и выбираю библиотеку DemoServer. Теперь Visual Studio импортирует typelibrary и сгенерирует классы-обертки для DemoServer automation-класса. В моем проекте теперь есть пространство имен interop.DemoServer, которое содержит MyDemoClass, который реализует интерфейс ImyDemo, которой содержит метод MyMethod.

Я могу использовать automation-класс, как и любой другой класс .NET. По клику на Button2 создается automation-объект и вызывается его метод.

private void Button2_Click(object sender, System.EventArgs e)

{

DemoServer.MyDemoClass axo = new DemoServer.MyDemoClass();

Label1.Text = axo.MyMethod(TextBox1.Text);

}


Вот и все. Весь код исполняется сервере до передачи клиенту в отдельном от веб-страницы файле. Мне доступны все серверные компоненты, в том числе серверные элементы управления, мне больше не требуется TextBox для отображения результата, это сделает Label.

В ASP.NET можно продолжать использовать ваши automation-объекты благодаря тому что .NET Interop позволяет гладко интегрировать automation-объекты внутрь .NET-приложения. Объект запускается у клиента, фактически так же, как и до использования ASP.NET. Клиент не знает, что выполняется .NET, он просто запускает скрипт. ASP.NET предоставляет очень удобную функцию для предоставления сценариев клиентской стороне.

1 comment:

Алексей Петров said...

Это мой собственный перевод статьи Петера ван Оиджена (Peter van Ooijen ), посвященной использованию automation-объектов в ASP.NET. Оригинал статьи можно найти по адресу http://www.dotnetjunkies.com/tutorial/84c30d12-174d-48eb-83fd-f6a6a1e08c44.dcik
Поскольку мой английский оставляет желать лучшего, я буду рад сообщениям об ошибках и неточностях

 
Google+