Я разрабатываю библиотеку COM, которая использует IStream
интерфейс для чтения и записи данных. Мой код MIDL выглядит так:
interface IParser : IUnknown
{
HRESULT Load([in] IStream* stream, [out, retval] IParsable** pVal);
};
Поскольку IStream
и его базовый интерфейс ISequentialStream
не определены внутри библиотеки типов, они определены в моей. Все идет нормально. Однако, когда я просматриваю свою библиотеку типов с помощью OLEView, ISequentialStream
определяет только элементы RemoteRead
и RemoteWrite
, в то время как я ожидал Read
и Write
, поскольку именно их я вызываю. Еще более странно то, что MSDN перечисляет эти два члена (в дополнение к исходным), но заявляет, что они не поддерживаются.
Вопрос
Итак, что это за элементы и как их использовать из клиента (например, управляемое приложение для создания управляемой оболочки Stream
для IStream
)?
Долгая история
Я хочу реализовать оболочку на стороне клиента, которая перенаправляет вызовы IStream
в потоки .NET, например System.IO.FileStream
. Эта оболочка может наследоваться от IStream
следующим образом:
public class Stream : Lib.IStream
{
public System.IO.Stream BaseStream { get; private set; }
public Stream(System.IO.Stream stream)
{
this.BaseStream = stream;
}
// All IStream members in here...
public void Read(byte[] buffer, int bufferSize, IntPtr bytesReadPtr)
{
// further implementation...
this.BaseStream.Read();
}
}
И затем я хочу вызвать свой сервер с помощью этой оболочки:
var wrapper = new Stream(baseStream);
var parsable = parser.Load(wrapper);
Проблема в том, что Lib.Stream
в предыдущем примере предоставляет только RemoteRead
и RemoteWrite
, так что вызовы сервера к stream->Read()
окажутся в ничейной зоне. Насколько я понял, для управляемых COM-серверов существует System.Runtime.InteropServices.ComTypes.IStream
, но в моем примере у меня есть неуправляемый COM-сервер и управляемый клиент, который должен предоставлять IStream
экземпляров.
IStream
не совместим с автоматизацией; неразумно пытаться определить его в библиотеке типов. Если вам нужно, чтобыIParser
был совместим с автоматизацией, возьмитеIUnknown*
в качестве первого параметра и запросите его дляIStream
в реализации. Либо удалите методLoad
изIParser
, реализуйте объектIPersistStreamInit
(вместе с его методомLoad
) и добавьте свойство, возвращающееIParsable
. - person Igor Tandetnik   schedule 07.11.2013IPersistStreamInit
- он также используетIStream
в качестве параметра, что приводит к тому же результату, что описан выше (IStream
добавляется в мою библиотеку типов). Насколько я могу судить, это поведение MIDL по умолчанию, не так ли?! - person Carsten   schedule 07.11.2013Read
/Write
, например, наSystem.IO.FileStream
) на стороне клиента, но у меня там нетRead
/Write
. ИнтерфейсIStream
(вы имеете в виду прокси?!) из моей библиотеки типов определяет толькоRemoteRead
иRemoteWrite
. - person Carsten   schedule 07.11.2013System.IO.Stream
, а неIStream
. Также моя реальная проблема отличается от той, что указана в вопросе, как описано выше. - person Carsten   schedule 07.11.2013IPersistStreamInit
в своем IDL. Не каждый интерфейс, реализуемый вашим объектом, должен или должен быть описан в IDL — вам нужны только те, для которых вы хотите использовать скрипты, и те, для которых вы хотите универсальное маршалирование. - person Igor Tandetnik   schedule 07.11.2013Load
/Save
из клиентского кода? - person Carsten   schedule 07.11.2013QueryInterface
. Спасибо :) - person Carsten   schedule 07.11.2013