Поскольку слой взаимодействия с СОМ поначалу может несколько ошеломить, давайте на минуту забудем обо всех формальных определениях
j
и перейдем к реальному примеру, иллюстрирующему применение ком- / понента СОМ из приложения .NET. По мере продвижения вперед я буду/ давать разъяснение происходящих событий и расскажу, как использовать приобретенные знания в ваших приложениях.
В этом примере мы предположим, что у нас есть СОМ-компонент Airlinelnfo, написанный на Microsoft Visual C++ с ATL. Я не будут освещать здесь все этапы создания этого компонента, потому что хочу сосредоточиться на вопросах, связанных с .NET и С#. Однако я разъясню этот выдающийся код (полный проект Visual C++ находится на CD, прилагаемом к этой книге).
Наш компонент СОМ разработан для того, чтобы выдавать подробности о прибытии рейсов некоторой авиалинии. Для простоты допустим, что компонент возвращает данные для авиалинии Air Scooby 1C 5678, а в случае любой другой авиалинии — ошибку. Я намеренно вставил механизм генерации ошибки, чтобы показать вам, как ошибка, возникшая в компоненте СОМ, может проходить в обратном направлении и перехватываться вызывающим клиентским приложением .NET. Вот IDL для компонента СОМ:
interface lAirlinelnfo : IDispatch {
[id(1), helpstring("method GetAirlineTiming")]
HRESULT GetAirlineTiming([in] BSTR bstrAirline, [out,retval] BSTR* pBstrDetails);
[propget, id(2), helpstring("property LocalTiraeAtOrlando")] HRESULT LocalTimeAtOrlando([out, retval] BSTR •pVal); };
Ничего особенного, даже для самых неопытных разработчиков СОМ. У нас есть интерфейс с именем
lAirlinelnfo
и двумя методами:
GetAirlineTiming
и
LocalTimeAtOrlando.
А теперь взгляните на настоящую реализацию метода
GetAirlineTiming:
STDMETHODIMP CAirlineInfo::GetAirlineTiming(BSTR bstrAirline, BSTR *pBstrDetails)
{
\ _bstr_t bstrQueryAirline(bstrAirline);
\
if(NULL == pBstrDetails) return E.POINTER;
\ if(_bstr_t("Air Scooby 1C 5678") ==
\ bstrdueryAirline)
\ {
I // Вернуть расписание для этой авиалинии.
\
"pBstrDetails =
| _bstr_t(_T("16:45:00 - Will
arrive at Terminal 3")).copy();
}
else
{
II
Вернуть сообщение об ошибке.
return Error(LPCTSTR(_T("Not available" )),
__uuidof(Airlinelnfo),
AIRLINE_NOT_FOUND);
>
return S_OK; }
Метод
GetAirlineTiming
принимает два аргумента. Первый
(bstrAirline) —
это строка
BSTR,
представляющая авиалинию, а второй
(pBstrDetails) —
выходной параметр, возвращающий информацию о прибытии (местное время и проход для регистрации). В этом методе мы проверяем, равно ли значение входного параметра
bstrAirline
строке
"Air Scooby 1C 5678".
Если это так, то мы возвращаем некоторую жестко заданную информацию о прибытии. Если значение не совпадает с ожидаемым, мы вызываем метод ошибки, чтобы вернуть уведомление о том, что поддерживается только одна авиалиния.
Закончив с обзором основ использования компонентов, рассмотрим генерирование метаданных из библиотеки типов компонента (typelib), которые .NET-клиент может использовать для "переговоров" с нашим компонентом и вызова его методов.