WriteableOnDemandStream.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / TrustUi / MS / Internal / documents / Application / WriteableOnDemandStream.cs / 1 / WriteableOnDemandStream.cs

                            //------------------------------------------------------------------------------ 
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved. 
//
//  
// This class acts as a type of proxy; it is responsible for forwarding all
// stream requests to the active stream.  Unlike a proxy it is also controls 
// which stream is active. Initially the active stream is the stream provided 
// at construction, at the time of the first write operation the active stream
// is replaced with one provided by a delegate. 
//
// History:
//  07/04/2005: [....]: Initial implementation.
//  08/28/2005: [....]: Adjusted spacing and style to match team better 
//-----------------------------------------------------------------------------
 
using System; 
using System.IO;
using System.Windows.TrustUI; 

namespace MS.Internal.Documents.Application
{
///  
/// This class acts as a type of proxy; it is responsible for forwarding all
/// stream requests to the active stream.  Unlike a proxy it is also 
/// controls which stream is active. Initially the active stream is the 
/// stream provided on construction, at the time of the first write
/// operation the active stream is replaced with one provided by a delegate. 
/// 
/// 
/// As this class only proxies the abstract methods of Stream, if we are
/// proxing a stream that has overriden other virutal methods behavioral 
/// inconsistencies may occur.  This could be solved by forwarding all
/// calls.  For internal use it is not currently needed. 
///  
internal sealed class WriteableOnDemandStream : Stream
{ 
    #region Constructors
    //-------------------------------------------------------------------------
    // Constructors
    //------------------------------------------------------------------------- 

    ///  
    /// Constructs the class with readingStream as the active Stream. 
    /// 
    ///  
    /// The read only Stream.
    /// FileMode that will be use to create write
    /// stream.
    /// FileAccess that will be use to create write 
    /// stream.
    /// Delegate used to create a 
    /// write stream on first write operation. 
    internal WriteableOnDemandStream(
        Stream readingStream, 
        FileMode mode,
        FileAccess access,
        GetWriteableInstance writeableStreamFactory)
    { 
        if (readingStream == null)
        { 
            throw new ArgumentNullException("readingStream"); 
        }
 
        if (writeableStreamFactory == null)
        {
            throw new ArgumentNullException("writeableStreamFactory");
        } 

        _active = readingStream; 
        _mode = mode; 
        _access = access;
        _writeableStreamFactory = writeableStreamFactory; 
        _wantedWrite = ((_access == FileAccess.ReadWrite)
            || (_access == FileAccess.Write));

    } 
    #endregion Constructors
 
    #region Stream Overrides 
    //--------------------------------------------------------------------------
    // Stream Overrides 
    //-------------------------------------------------------------------------
    // Due to sub-nesting of pure proxies vs. decorating ones code structure
    // is simplier in this case by grouping Methods & Properies.
 
    #region Pure Proxies for Stream
    //-------------------------------------------------------------------------- 
    // This region of code simply follows the proxy patern and only forwards 
    // the calls to the active stream.
    //-------------------------------------------------------------------------- 

    /// 
    /// 
    ///  
    public override bool CanRead
    { 
        get 
        {
            return _active.CanRead; 
        }
    }

    ///  
    /// 
    ///  
    public override bool CanSeek 
    {
        get 
        {
            return _active.CanSeek;
        }
    } 

    ///  
    ///  
    /// 
    public override void Flush() 
    {
        Trace.SafeWriteIf(
            _isActiveWriteable,
            Trace.Packaging, 
            "Flush is being called on read-only stream.");
 
        if (_isActiveWriteable) 
        {
            _active.Flush(); 
        }
    }

    ///  
    /// 
    ///  
    public override long Length 
    {
        get 
        {
            return _active.Length;
        }
    } 

    ///  
    ///  
    /// 
    public override long Position 
    {
        get
        {
            return _active.Position; 
        }
        set 
        { 
            _active.Position = value;
        } 
    }

    /// 
    ///  
    /// 
    public override int Read(byte[] buffer, int offset, int count) 
    { 
        return _active.Read(buffer, offset, count);
    } 

    /// 
    /// 
    ///  
    public override long Seek(long offset, SeekOrigin origin)
    { 
        return _active.Seek(offset, origin); 
    }
    #endregion Pure Proxies for Stream 

    #region Decorating Proxies for Stream
    //-------------------------------------------------------------------------
    // This region of code follows the decorator patern, the added behavior 
    // is the replacement of the active stream with one that is writeable
    // on the first write operation. 
    //-------------------------------------------------------------------------- 

    ///  
    /// 
    /// 
    public override bool CanWrite
    { 
        get
        { 
            // asking if we can write is not a write operation, 
            // however, as the active type had to implement this
            // abstract property thier implementation is the one 
            // we should prefer, when we are writable, until then
            // it's more efficent to assume if the user asked for
            // write it will be supported
            if (_isActiveWriteable) 
            {
                return _active.CanWrite; 
            } 
            else
            { 
                return _wantedWrite;
            }
        }
    } 

    ///  
    ///  
    /// 
    public override void SetLength(long value) 
    {
        EnsureWritable();
        _active.SetLength(value);
    } 

    ///  
    ///  
    /// 
    public override void Write(byte[] buffer, int offset, int count) 
    {
        EnsureWritable();
        _active.Write(buffer, offset, count);
    } 
    #endregion Decorating Proxies for Stream
    #endregion Stream Overrides 
 
    #region Internal Delegates
    //------------------------------------------------------------------------- 
    // Internal Delegates
    //-------------------------------------------------------------------------

    ///  
    /// The delegate is use as a factory to return writable copy of the
    /// stream we were originally given. 
    ///  
    /// The FileMode desired.
    /// The FileAccess desired. 
    /// A writeable Stream.
    public delegate Stream GetWriteableInstance(
        FileMode mode,
        FileAccess access); 
    #endregion Internal Delegates
 
    #region Protected Methods - Stream Overrides 
    //-------------------------------------------------------------------------
    // Protected Methods - Stream Overrides 
    //--------------------------------------------------------------------------

    /// 
    /// Ensure we do not aquire new resources. 
    /// 
    /// Indicates if we are disposing. 
    protected override void Dispose(bool disposing) 
    {
        try 
        {
            if (disposing)
            {
                if (_isActiveWriteable && _active.CanWrite) 
                {
                    _active.Flush(); 
                    // we do not want to dispose of _active 
                    // first we are merely a proxy; and being done with
                    // us is not the same as being done with the PackagePart 
                    // it supprots, the Package which created _active
                    // is calls dispose
                }
                _isActiveWriteable = true; 
            }
        } 
        finally 
        {
            base.Dispose(disposing); 
        }
    }
    #endregion Protected Methods - Stream Overrides
 
    #region Private Methods
    //------------------------------------------------------------------------- 
    // Private Methods 
    //--------------------------------------------------------------------------
 
    /// 
    /// Ensures either the active stream is our writeable stream or uses the
    /// factory delegate to get one and assign it as the active stream.
    ///  
    /// 
    ///  
    private void EnsureWritable() 
    {
        if (!_wantedWrite) 
        {
            throw new NotSupportedException(
                SR.Get(SRID.PackagingWriteNotSupported));
        } 

        if (!_isActiveWriteable) 
        { 
            Stream writer = _writeableStreamFactory(_mode, _access);
            if (writer == null) 
            {
                throw new IOException(
                    SR.Get(SRID.PackagingWriteableDelegateGaveNullStream));
            } 

            if (writer.Equals(this)) 
            { 
                throw new IOException(
                    SR.Get(SRID.PackagingCircularReference)); 
            }

            writer.Position = _active.Position;
 
            _active = writer;
            _isActiveWriteable = true; 
        } 
    }
    #endregion Private Methods 

    #region Private Fields
    //--------------------------------------------------------------------------
    // Private Fields 
    //-------------------------------------------------------------------------
 
    ///  
    /// The delegate we were given to have a writeable stream created.
    ///  
    private GetWriteableInstance _writeableStreamFactory;
    /// 
    /// The stream we should be currently using.
    ///  
    private Stream _active;
    ///  
    /// Whether the active stream is writeable. 
    /// 
    private bool _isActiveWriteable; 
    /// 
    /// The caller's desired FileMode provided on construction.
    /// 
    private FileMode _mode; 
    /// 
    /// The caller's desired FileAccess provided on construction. 
    ///  
    private FileAccess _access;
    ///  
    /// Calculated using FileAccess, it determines if writing was indicated.
    /// 
    private bool _wantedWrite;
    #endregion Private Methods 
}
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK