Реализация интерфейса IServiceProvider в классе, наследующем другие интерфейсы в Delphi и Pascal
Интерфейс IServiceProvider является частью технологии COM (Component Object Model) и используется для получения доступа к различным сервисам, предоставляемым объектом. В этом материале мы рассмотрим, как реализовать интерфейс IServiceProvider в классе, наследующем другие интерфейсы, в языках программирования Delphi и Pascal.
Прежде всего, давайте рассмотрим структуру класса, который будет реализовывать интерфейс IServiceProvider. Пусть у нас есть класс TPassthrough, который наследует интерфейсы IInternetProtocolRoot, IInternetProtocolSink, IInternetProtocol и IServiceProvider.
TPassthrough = class(TComObject, IInternetProtocolRoot, IInternetProtocolSink, IInternetProtocol, IServiceProvider)
private
FDefaultSink: IInternetProtocol;
FProtSink: IInternetProtocolSink;
FBindInfo: IInternetBindInfo;
public
{ IServiceProvider }
function QueryService(const rsid, iid: TGuid; out Obj): HResult; stdcall;
{ IInternetProtocolSink }
function Switch(const ProtocolData: TProtocolData): HResult; stdcall;
function ReportProgress(ulStatusCode: ULONG; szStatusText: LPCWSTR): HResult; stdcall;
function ReportData(grfBSCF: DWORD; ulProgress, ulProgressMax: ULONG): HResult; stdcall;
function ReportResult(hrResult: HResult; dwError: DWORD; szResult: LPCWSTR): HResult; stdcall;
{ IInternetProtocolRoot }
function Start(szUrl: LPCWSTR; OIProtSink: IInternetProtocolSink; OIBindInfo: IInternetBindInfo; grfPI, dwReserved: DWORD): HResult; stdcall;
function Continue(const ProtocolData: TProtocolData): HResult; overload; stdcall;
function Abort(hrReason: HResult; dwOptions: DWORD): HResult; stdcall;
function Terminate(dwOptions: DWORD): HResult; stdcall;
function Suspend: HResult; stdcall;
function Resume: HResult; stdcall;
{ IInternetProtocol }
function Read(pv: Pointer; cb: ULONG; out cbRead: ULONG): HResult; stdcall;
function Seek(dlibMove: LARGE_INTEGER; dwOrigin: DWORD; out libNewPosition: ULARGE_INTEGER): HResult; stdcall;
function LockRequest(dwOptions: DWORD): HResult; stdcall;
function UnlockRequest: HResult; stdcall;
end;
Теперь давайте реализуем метод QueryService интерфейса IServiceProvider. Этот метод должен возвращать указатель на объект, реализующий запрошенный сервис, или указатель на сам объект, если он предоставляет этот сервис. Если сервис не найден, метод должен вернуть E_NOTIMPL.
function TPassthrough.QueryService(const rsid, iid: TGuid; out Obj): HResult; stdcall;
begin
Result := E_NOINTERFACE;
Pointer(Obj) := nil;
if Assigned(FDefaultSink) and (FDefaultSink as IServiceProvider).QueryService(rsid, iid, Obj) = S_OK then
Result := S_OK
else
begin
if Succeeded(QueryInterface(iid, Obj)) then
Result := S_OK;
end;
end;
В методе QueryService мы сначала пытаемся запросить сервис у объекта FDefaultSink. Если это не удается, мы пытаемся запросить сервис у самого объекта TPassthrough с помощью вызова QueryInterface. Если и это не удается, мы возвращаем E_NOINTERFACE.
Обратите внимание, что мы используем оператор Assigned для проверки, назначен ли указатель на объект FDefaultSink. Это важно, чтобы избежать доступа к неинициализированной памяти.
Также стоит отметить, что мы не добавляем счетчик ссылок на объект Obj после успешного запроса интерфейса. Это необходимо сделать, чтобы избежать утечек памяти. Однако, это выходит за рамки данного материала.
Используя данную реализацию, вы сможете запросить сервис у объекта TPassthrough, реализующего интерфейс IServiceProvider, и получить указатель на объект, предоставляющий этот сервис. Это может быть полезно при работе с технологией COM и другими
Реализация интерфейса `IServiceProvider` в классе, наследующем другие интерфейсы в Delphi и Pascal
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.