Поиск

Использование динамического определения типов для выбора интерфейсов СОМ

Как же работает классический сценарий Query Interface с точки зрения .NET-клиента, которому нужен доступ к другому интерфейсу, реализованному объектом СОМ? Все, что вам нужно, чтобы выполнить запрос QI для другого интерфейса, — это привести текущий объект к другому нужному вам интерфейсу, и — пожалуйста! — ваш запрос QI выполнен! Теперь вы готовы к вызову всех методов и свойств нужного интерфейса. Это просто.

Вся черновая закулисная работа снова достается RCW. В этом смысле она аналогична исполняющей среде Visual Basic, которая защищает разработчиков клиентов СОМ от написания любого явного кода, связанного с Query Interface. Она просто выполняет для вас запросы QI, когда вы устанавливаете объект одного типа как объект другого ассоциированного типа.

Посмотрим на этот механизм в действии, чтобы узнать, как легко его использовать. Имея в виду наш пример, предположим, что вы хотели вызвать методы интерфейса lAirportFacilities, которые для нашего объекта СОМ реализованы другим интерфейсом. Для этого вам будет нужно привести объект Airlinelnfo к интерфейсу lAirportFacilities. Теперь вы можете вызывать все методы, которые являются частью интерфейса lAirportFacilities. Но перед приведением вы, возможно, захотите проверить, поддерживает или реализует ли имеющийся в данный момент экземпляр объекта тип интерфейса, который мы запрашиваем. Это можно сделать, вызвав метод IsInstanceOf класса System. Type. Если он возвращает true, вы знаете, что QI выполнен успешно и можно выполнить приведение. В случае приведения объекта к некоторому интерфейсу, не поддерживаемому этим объектом, генерируется исключение System.InvalidCastExcep-tion. Таким образом, RCW гарантирует, что выполняется приведение только к интерфейсам, реализованным объектом СОМ. Вот как это выглядит в написанном коде:

using System;
using System.Runtime.InteropServices;
using System.Reflection;
using AIRLINEINFORMATIONLib;
public class AirlineClient2App {
public static void Main() {
///////////////////////////////////////////////
/// Запрос интерфейса/проверка типа в период выполнения.
///////////////////////////////////////////////
try
{
Airlinelnfo objAirlinelnfo;
lAirportFacilitiesInfo objFacilitiesInfo;
// Создать новый объект Airlinelnfo.
objAirlinelnfo = new AirlinelnfoO;
// Вызвать метод GetAirlineTiming. String
strDetails = objAirlinelnfo.GetAirlineTiming
(strAirline);
// Запросить интерфейс lAirportFacilitiesInfo. objFacilitiesInfo .=
(lAirportFacilitiesInfo)objAirlinelnfo;
//Вызвать метод интерфейса lAirportFacilitiesInfo
Console.WriteLine("{0}", objFacilitiesInfo.GetlnternetCafeLocationsO);
>
catch(InvalidCastException eCast)
<
Console.WriteLine("We got an InvalidCast Exception " +
"- Message is {0}",eCast.Message); } > >