Прежде всего, это не дубликат этого Does a wrapper class for a COM interop IStream already exist?, потому что мне нужна реализация в другом направлении. Мне нужно создать реализацию IStream от IO.Stream до IStream. Но прежде чем я начну пытаться это сделать, хотел спросить, знает ли кто-нибудь уже существующее воплощение или какие-либо статьи об этом. Я не смог найти что-либо в рамках .net, и Google просто дал мне результаты внедрения IStream в IO.Stream. Так у кого-нибудь хороший отзыв для меня? Я действительно не знаю, как начать, потому что первый член (Clone -> Создает новый объект потока, который ссылается на те же байты, что и исходный поток, но предоставляет отдельный указатель поиска на эти байты) вызывает у меня проблемы. Я понятия не имею, как это сделать на основе IO.Stream.C# IStream реализация IStream
8
A
ответ
5
Наконец, я сделал это сам (не стесняйтесь копировать и изменять его):
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("0000000c-0000-0000-C000-000000000046")]
public interface IStream
{
[PreserveSig]
HResult Read([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] [Out] byte[] pv, int cb, IntPtr pcbRead);
[PreserveSig]
HResult Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pv, int cb, IntPtr pcbWritten);
[PreserveSig]
HResult Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition);
[PreserveSig]
HResult SetSize(long libNewSize);
HResult CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten);
[PreserveSig]
HResult Commit(int grfCommitFlags);
[PreserveSig]
HResult Revert();
[PreserveSig]
HResult LockRegion(long libOffset, long cb, int dwLockType);
[PreserveSig]
HResult UnlockRegion(long libOffset, long cb, int dwLockType);
[PreserveSig]
HResult Stat(out comtypes.STATSTG pstatstg, int grfStatFlag);
[PreserveSig]
HResult Clone(out IStream ppstm);
}
/// <summary>
/// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms752876(v=vs.85).aspx
/// </summary>
public class ComStream : Stream, IStream
{
private Stream _stream;
public ComStream(Stream stream)
: this(stream, true)
{
}
internal ComStream(Stream stream, bool sync)
{
if (stream == null)
throw new ArgumentNullException("stream");
if (sync)
{
stream = Stream.Synchronized(stream);
}
_stream = stream;
}
HResult IStream.Clone(out IStream ppstm)
{
//ComStream newstream = new ComStream(_stream, false);
//ppstm = newstream;
ppstm = null;
return HResult.E_NOTIMPL;
}
HResult IStream.Commit(int grfCommitFlags)
{
return HResult.E_NOTIMPL;
}
HResult IStream.CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
{
return HResult.E_NOTIMPL;
}
HResult IStream.LockRegion(long libOffset, long cb, int dwLockType)
{
return HResult.E_NOTIMPL;
}
HResult IStream.Read(byte[] pv, int cb, IntPtr pcbRead)
{
if (!CanRead)
throw new InvalidOperationException("Stream not readable");
int read = Read(pv, 0, cb);
if (pcbRead != IntPtr.Zero)
Marshal.WriteInt64(pcbRead, read);
return HResult.S_OK;
}
HResult IStream.Revert()
{
return HResult.E_NOTIMPL;
}
HResult IStream.Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
{
SeekOrigin origin = (SeekOrigin)dwOrigin; //hope that the SeekOrigin enumeration won't change
long pos = Seek(dlibMove, origin);
if (plibNewPosition != IntPtr.Zero)
Marshal.WriteInt64(plibNewPosition, pos);
return HResult.S_OK;
}
HResult IStream.SetSize(long libNewSize)
{
return HResult.E_NOTIMPL;
}
HResult IStream.Stat(out comtypes.STATSTG pstatstg, int grfStatFlag)
{
pstatstg = new comtypes.STATSTG();
pstatstg.cbSize = Length;
return HResult.S_OK;
}
HResult IStream.UnlockRegion(long libOffset, long cb, int dwLockType)
{
return HResult.E_NOTIMPL;
}
HResult IStream.Write(byte[] pv, int cb, IntPtr pcbWritten)
{
if (!CanWrite)
throw new InvalidOperationException("Stream is not writeable.");
Write(pv, 0, cb);
if (pcbWritten != null)
Marshal.WriteInt32(pcbWritten, cb);
return HResult.S_OK;
}
public override bool CanRead
{
get { return _stream.CanRead; }
}
public override bool CanSeek
{
get { return _stream.CanSeek; }
}
public override bool CanWrite
{
get { return _stream.CanWrite; }
}
public override void Flush()
{
_stream.Flush();
}
public override long Length
{
get { return _stream.Length; }
}
public override long Position
{
get
{
return _stream.Position;
}
set
{
_stream.Position = value;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
return _stream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return _stream.Seek(offset, origin);
}
public override void SetLength(long value)
{
_stream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
_stream.Write(buffer, offset, count);
}
protected override void Dispose(bool disposing)
{
if (_stream != null)
{
_stream.Dispose();
_stream = null;
}
}
}
Смежные вопросы
- 1. Использование станд :: IStream :: часовому с станд :: IStream
- 2. "carbon-copy" C++ istream?
- 3. C++ Iterate istream
- 4. C++ istream with lex
- 5. Перегрузка оператора istream C++
- 6. istream :: operator >> or istream :: get
- 7. перегрузка istream
- 8. istream operator
- 9. C++ IStream оператор >>
- 10. ВФ из IStream в C++
- 11. Как получить длину IStream? C++
- 12. C++ предупреждение решения IStream :: tellg
- 13. C ФАЙЛ * to ostream/istream
- 14. C++/CLI-оболочка для istream
- 15. Ruby эквивалент оператора C++ istream?
- 16. Объявление generic istream в C++
- 17. function with istream & parameter C++
- 18. Функция C++ с istream & parameter
- 19. Winforms RichTextBox as istream
- 20. Pseudo-istream pointer return
- 21. istream with popen функциональность
- 22. Создание настраиваемого манипулятора istream
- 23. std :: istream :: получить эффективность
- 24. Запись массива в IStream
- 25. istream get method поведение
- 26. Initiliaze IFilter от IStream
- 27. Преобразование istream operator >> to istream getline
- 28. Перегрузка оператора: Ostream/Istream
- 29. Разница между IStream :: читать и IStream :: оператор >>
- 30. istream stop at \ n
СОМ клиент будет в конечном итоге, призывающую :: Release() на IUnknown COM-интерфейс/CCW, но нет способа перехватить это до .Dispose()? – toong
Не работает как есть, даже если он появляется: System.IO.Stream.Read() разрешено вернуться раньше и сказать, что он не прочитал все байты, а только один или несколько. IStream :: Read() * всегда * считывает все запрошенные байты, если не достигнут конец потока. Различные, несовместимые контракты: вы должны добавить цикл чтения в вашу реализацию IStream.Read() и прочитать/заполнить буфер до тех пор, пока вы не получите все запрошенные байты, или читать больше нет. –