TreeBuilderBamlTranslator.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 / Framework / System / Windows / Markup / TreeBuilderBamlTranslator.cs / 1 / TreeBuilderBamlTranslator.cs

                            /****************************************************************************\ 
*
* File: TreeBuilderBamlTranslator.cs
*
* Purpose: Class that builds a stream from BAML 
*
* History: 
*    6/06/01:    rogerg        Created 
*    5/29/03:    [....]      Ported to wcp
* 
* Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
*
\***************************************************************************/
 
using System;
using System.Xml; 
using System.IO; 
using System.Windows;
using System.Text; 
using System.Collections;
using System.ComponentModel;

using System.Diagnostics; 
using System.Reflection;
using System.Threading; 
using MS.Internal; 
using MS.Utility;
 
// Disabling 1634 and 1691:
// In order to avoid generating warnings about unknown message numbers and
// unknown pragmas when compiling C# source code with the C# compiler,
// you need to disable warnings 1634 and 1691. (Presharp Documentation) 
#pragma warning disable 1634, 1691
 
#if PBTCOMPILER 
namespace MS.Internal.Markup
#else 
namespace System.Windows.Markup
#endif
{
 
    /// 
    /// TreeBuilder implementation for building a Tree from BAML 
    ///  
    internal class TreeBuilderBamlTranslator : TreeBuilder
    { 
#if !PBTCOMPILER

#region Constructors
 
        /// 
        /// Constructor.  If closeBamlStream is true, then the parser is the owner of the 
        /// owner of the stream, and will close the stream when finished parsing. 
        /// 
        internal TreeBuilderBamlTranslator( 
            Stream bamlStream,
            ParserContext parserContext,
            object parent,
            bool closeBamlStream) 
            : base()
        { 
            _bamlStream = bamlStream; 
            _closeBamlStream = closeBamlStream;
 
            Debug.Assert(null != parserContext.XamlTypeMapper);

            RecordReader = new BamlRecordReader(bamlStream, parserContext, parent);
        } 

        // internal constructor to allow subclassing. 
        internal TreeBuilderBamlTranslator() 
        {
        } 

#endregion Constructors

#region Overrides 

        ///  
        /// Internal Avalon method. Used to parse a BAML file. 
        /// 
        /// An array containing the root objects in the BAML stream 
        public override object ParseFragment()
        {
            bool asyncParse = false; // only close stream if not in Async parse mode.
 
            try
            { 
                RecordReader.Initialize(); 

                RecordReader.ReadVersionHeader(); 

                // if baml, read the start document and get the ParseMode.
                // Review, should probably be done in Parse()
                BamlRecordType recType = (BamlRecordType)RecordReader.BinaryReader.ReadByte(); 
                if (recType != BamlRecordType.DocumentStart)
                { 
                    throw new InvalidOperationException(); 
                }
 
                BamlRecord bamlRecord = RecordReader.BamlRecordManager.ReadNextRecord(
                                                            RecordReader.BinaryReader,
                                                            Int64.MaxValue,
                                                            recType); 
                Debug.Assert(null != bamlRecord);
                Debug.Assert(bamlRecord.RecordType == BamlRecordType.DocumentStart); 
 
                BamlDocumentStartRecord bamlStartDoc = bamlRecord as BamlDocumentStartRecord;
 
                if (null != bamlStartDoc)
                {
                    // SetParse Mode may have already change the ParseMode so
                    // only use what is in the record if still Uninitialized. 
                    if ( XamlParseMode == XamlParseMode.Uninitialized )
                    { 
#if SUPPORTBAMLASYNC 
                        // For M11 we will not support async loading of baml files.  They
                        // will all be treated as synchronous.  This is done to reduce 
                        // surface area, as described in windows bug # 1079575
                        if (bamlStartDoc.LoadAsync)
                        {
                            XamlParseMode = XamlParseMode.Asynchronous; 
                        }
                        else 
#endif 
                        {
                            XamlParseMode = XamlParseMode.Synchronous; 
                        }
                    }

                    MaxAsyncRecords = bamlStartDoc.MaxAsyncRecords; 
                }
 
                // Set associated record reader async info to what has been found so far 
                RecordReader.XamlParseMode = XamlParseMode;
                RecordReader.MaxAsyncRecords = MaxAsyncRecords; 
                RecordReader.IsDebugBamlStream = bamlStartDoc.DebugBaml;

                Debug.Assert(XamlParseMode != XamlParseMode.Uninitialized);
 
                // if in synchronous mode then just read the baml stream and then
                // return. if going into async mode then build up the first tag 
                // synchronously and then post a queue item. 
                // Note that we don't actually go into async mode for compiling.
                if (XamlParseMode == XamlParseMode.Synchronous) 
                {
                    RecordReader.Read();
                    TreeBuildComplete();
                    //Debug.Assert(1 >= RootList.Count, "Cannot have multiple root elements in BAML stream"); 
                }
                else 
                { 

                    // read in the first record since binder at present 
                    // needs this.
                    bool moreData = true;

                    // sit in synchronous read until get first root. Need this 
                    // until we get async binder support.
                    while (GetRoot() == null && moreData) 
                    { 
                        moreData = RecordReader.Read(true /* single record  mode*/);
                    } 

                    if (moreData && GetRoot() == null)
                    {
                        // before going async want to switch to async stream interfaces 
                        // so we don't block on I/O.
 
                        // setup stream Manager on Reader and kick of Async Writes 

                        StreamManager = new ReadWriteStreamManager(); 

                        // RecordReader no points to the ReaderWriter stream which
                        // is different from our BAMLStream member.
                        RecordReader.BamlStream = StreamManager.ReaderStream; 

                        // now spin a thread to read the BAML. This can change 
                        // once we get Read support that fails if contents isn't 
                        // available instead of blocks.
 
                        asyncParse = true;

                        ThreadStart threadStart = new ThreadStart(ReadBamlAsync);
                        Thread thread = new Thread(threadStart); 
                        thread.Start();
 
                        // post a work item to do the rest. 
                        Post();
                    } 
                    else
                    {
                        // if don't get a root or there isn't any moredata then
                        // we are done building. 
                        TreeBuildComplete();
                    } 
                } 
            }
            finally 
            {
                // If not in an async parse and we are told to close the
                // stream explicitly, then we are done with the input stream.
                // Otherwise rely on the async thread calling Close 
                if (!asyncParse)
                { 
                    CloseBamlInputStream(); 
                }
            } 

            return GetRoot();
        }
 
        /// 
        ///  called when TreeBuilder gets an Async slice 
        ///  we override the base class to see if can close the input stream. 
        /// 
        internal override void HandleAsyncQueueItem() 
        {
            if (DoneReadingBamlStream)
            {
                CloseBamlInputStream(); 
            }
 
            base.HandleAsyncQueueItem(); 
        }
 
#endregion overrides


#region Methods 

        // Async callback that reads the next chunk from the baml stream, until the 
        // end of the stream has been reached, or we've read a certain number of 
        // records.
        protected void ReadBamlAsync() 
        {

            try
            { 
                // sits in a loop reading BAML
                // hopefully temporary function not needed when can get read to 
                // just fail if number of requested bytes are not yet available. 
                Debug.Assert(null != StreamManager,"StreamManager is null in Async Read");
                Debug.Assert(BamlStream != RecordReader.BamlStream,"Input BAML shouldn't be same as Output"); 

                WriterStream writerStream = StreamManager.WriterStream;
                int bytesRead;
                long writtenStreamLength = 0; 
                int maxBufferSize = 256; // for now read 256 at a time.
                byte[] buffer = new byte[maxBufferSize]; 
 
                while (!DoneReadingBamlStream)
                { 
                    bytesRead = BamlStream.Read(buffer,0,maxBufferSize);

                    if (0 == bytesRead)
                    { 
                        DoneReadingBamlStream = true;
                    } 
                    else 
                    {
                        writerStream.Write(buffer,0,bytesRead); 
                        writtenStreamLength += bytesRead;
                        writerStream.UpdateReaderLength(writtenStreamLength);
                    }
                } 
            }
            catch (Exception e) 
            { 
                if (CriticalExceptions.IsCriticalException(e))
                { 
                   throw;
                }
                else
                { 
                    // catch any exception on the async thread and send it over.
                    // make sure you set the exception before the error flag. 
                    ParseException = e; 
                }
            } 
        }

        /// 
        /// Helper Function to close the BamlInputStream. 
        /// This can get called twice in Async, once the first time we
        /// get on the UI thread after done reading input and second when 
        /// the tree buildComplete occurs so check for NULL 
        /// the queue
        ///  
        void CloseBamlInputStream()
        {

            // possible we have to close 
            // In the straight BamlLoad case we will have a BamlStream to Close
            // if we are given ownership of the BamlStream in BuildFromBaml. 
            if (null != BamlStream ) 
            {
                if (_closeBamlStream) 
                {
                    BamlStream.Close();
                }
 
                // even if we don't own the treat set the member to null
                _bamlStream = null; 
 
            }
 
        }

#endregion Methods
 
#region Properties
 
        ///  
        /// BamlStream to load from
        ///  
        protected Stream BamlStream
        {
            get { return _bamlStream; }
            set { _bamlStream = value; } 
        }
 
        ///  
        /// flag used in Async read sets to true when
        /// BamlStream has been completely read. 
        /// 
        protected bool DoneReadingBamlStream
        {
            get { return _doneReadingBamlStream; } 
            set {  _doneReadingBamlStream = value; }
        } 
 
        /// 
        /// ReaderWriterStream used if we kick off an Async Load. 
        /// 
        protected ReadWriteStreamManager StreamManager
        {
            get { return _streamManager; } 
            set { _streamManager = value; }
        } 
 
#endregion Properties
 
#region Data

        // Manager used to handle the stream operations.
        ReadWriteStreamManager _streamManager; 

        // Stream of baml records. 
        Stream                 _bamlStream; 

        // True if the parser owns the baml stream, and can close the stream 
        // when the parse is complete.  False if the stream is owned by someone
        // else, in which case the parser will not close it.
        bool                   _closeBamlStream;
 
        // True when baml stream has completed reading in async mode.
        bool                   _doneReadingBamlStream; 
 
#endregion Data
 
#endif // !PBTCOMPILER

    }
 
}

// 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