BamlRecords.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 / BamlRecords.cs / 1 / BamlRecords.cs

                            /****************************************************************************\ 
*
* File: BamlRecords.cs
*
* Purpose:  Contains implementation for specific BamlRecords 
*
* History: 
*    6/06/01:    rogerg        Created 
*    5/28/03:    [....]      Ported to wcp
*    10/6/03:    [....]      Reorganized to remove DP - clr distinction 
*
* Copyright (C) 2002 by Microsoft Corporation.  All rights reserved.
*
\***************************************************************************/ 
using System;
using System.Xml; 
using System.IO; 
using System.Text;
using System.Collections.Generic; 
using System.Collections;
using System.Globalization;
using System.ComponentModel;
using System.Security.Permissions; 
using System.Diagnostics;
using System.Reflection; 
using System.Collections.Specialized; 
using MS.Internal.IO.Packaging.CompoundFile;
 
#if !PBTCOMPILER
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading; 

using MS.Internal.PresentationFramework; // SafeSecurityHelper 
#endif 

using System.Runtime.InteropServices; 
using MS.Utility;
using MS.Internal;

// 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
{ 
    // Types of records.  Note that this is a superset of XamlNodeTypes 
    internal enum BamlRecordType : byte
    { 
        /// 
        /// Unknown Node
        /// 
        // !!BamlRecordManager class relies on Unknown = 0 for initialization 
        Unknown = 0,
 
        ///  
        /// Start Document Node
        ///  
        DocumentStart,              // 1

        /// 
        /// End Document Node 
        /// 
        DocumentEnd,                // 2 
 
        /// 
        /// Start Element Node, which may be a CLR object or a DependencyObject 
        /// 
        ElementStart,               // 3

        ///  
        /// End Element Node
        ///  
        ElementEnd,                 // 4 

        ///  
        /// Property Node, which may be a CLR property or a DependencyProperty
        /// 
        Property,                   // 5
 
        /// 
        /// Binary serialization of a property 
        ///  
        PropertyCustom,             // 6
 
        /// 
        /// Complex Property Node
        /// 
        PropertyComplexStart,       // 7 

        ///  
        /// End Complex Property Node 
        /// 
        PropertyComplexEnd,         // 8 

        /// 
        /// Start Array Property Node
        ///  
        PropertyArrayStart,         // 9
 
        ///  
        /// End Array Property Node
        ///  
        PropertyArrayEnd,           // 10

        /// 
        /// Star IList Property Node 
        /// 
        PropertyIListStart,         // 11 
 
        /// 
        /// End PropertyIListStart Node 
        /// 
        PropertyIListEnd,           // 12

        ///  
        /// Start IDictionary Property Node
        ///  
        PropertyIDictionaryStart,   // 13 

        ///  
        /// End IDictionary Property Node
        /// 
        PropertyIDictionaryEnd,     // 14
 
        /// 
        /// LiteralContent Node 
        ///  
        LiteralContent,             // 15
 
        /// 
        /// Text Node
        /// 
        Text,                       // 16 

        ///  
        /// Text that has an associated custom typeconverter 
        /// 
        TextWithConverter,          // 17 

        /// 
        /// RoutedEventNode
        ///  
        RoutedEvent,                // 18
 
        ///  
        /// ClrEvent Node
        ///  
        ClrEvent,                   // 19

        /// 
        /// XmlnsProperty Node 
        /// 
        XmlnsProperty,              // 20 
 
        /// 
        /// XmlAttribute Node 
        /// 
        XmlAttribute,               // 21

        ///  
        /// Processing Intstruction Node
        ///  
        ProcessingInstruction,      // 22 

        ///  
        /// Comment Node
        /// 
        Comment,                    // 23
 
        /// 
        /// DefTag Node 
        ///  
        DefTag,                     // 24
 
        /// 
        /// x:name="value" attribute.  One typical use of this
        /// attribute is to define a key to use when inserting an item into an IDictionary
        ///  
        DefAttribute,               // 25
 
        ///  
        /// EndAttributes Node
        ///  
        EndAttributes,              // 26

        /// 
        /// PI xml - clr namespace mapping 
        /// 
        PIMapping,                  // 27 
 
        /// 
        /// Assembly information 
        /// 
        AssemblyInfo,               // 28

        ///  
        /// Type information
        ///  
        TypeInfo,                   // 29 

        ///  
        /// Type information for a Type that has an associated custom serializer
        /// 
        TypeSerializerInfo,         // 30
 
        /// 
        /// Attribute (eg - properties and events) information 
        ///  
        AttributeInfo,              // 31
 
        /// 
        /// Resource information
        /// 
        StringInfo,                 // 32 

        ///  
        /// Property Resource Reference 
        /// 
        PropertyStringReference,    // 33 

        /// 
        /// Record for setting a property to a Type reference.  This is used for
        /// properties that are of type "Type" 
        /// 
        PropertyTypeReference,      // 34 
 
        /// 
        /// Property that has a simple MarkupExtension value. 
        /// 
        PropertyWithExtension,      // 35

        ///  
        /// Property that has an associated custom typeconverter
        ///  
        PropertyWithConverter,      // 36 

        ///  
        /// Start a deferable content block
        /// 
        DeferableContentStart,      // 37
 
        /// 
        /// x:name="value" attribute when used within a defer load 
        /// dictionary.  These keys are hoisted to the front of the dictionary when 
        /// written to baml.
        ///  
        DefAttributeKeyString,      // 38

        /// 
        /// Implied key that is a Type attribute when used within a defer load 
        /// dictionary.  These keys are hoisted to the front of the dictionary when
        /// written to baml. 
        ///  
        DefAttributeKeyType,        // 39
 
        /// 
        /// This marks the start of an element tree that is used as the key in
        /// an IDictionary.
        ///  
        KeyElementStart,            // 40
 
 
        /// 
        /// This marks the end of an element tree that is used as the key in 
        /// an IDictionary.
        /// 
        KeyElementEnd,              // 41
 
        /// 
        /// Record marks the start of a section containing constructor parameters 
        ///  
        ConstructorParametersStart, // 42
 
        /// 
        /// Record marks the end of a section containing constructor parameters
        /// 
        ConstructorParametersEnd,   // 43 

        ///  
        /// Constructor parameter that has been resolved to a Type. 
        /// 
        ConstructorParameterType,   // 44 

        /// 
        /// Record that has info about which event or id to connect to in an object tree.
        ///  
        ConnectionId,               // 45
 
        ///  
        /// Record that set the conntent property context for the element
        ///  
        ContentProperty,            // 46

        /// 
        /// ElementStartRecord that also carries an element name. 
        /// 
        NamedElementStart,          // 47 
 
        /// 
        /// Start of StaticResourceExtension within the header of a deferred section. 
        /// 
        StaticResourceStart,        // 48

        ///  
        /// End of a StaticResourceExtension within the header of a deferred section.
        ///  
        StaticResourceEnd,          // 49 

        ///  
        /// BamlRecord that carries an identifier for a StaticResourceExtension
        /// within the header of a deferred section.
        /// 
        StaticResourceId,           // 50 

        ///  
        /// This is a TextRecord that holds an Id for the String value it represents. 
        /// 
        TextWithId,                 // 51 

        /// 
        /// PresentationOptions:Freeze="value" attribute. Used for ignorable
        /// WPF-specific parsing options 
        /// 
        PresentationOptionsAttribute, // 52 
 
        /// 
        /// Debugging information record that holds the source XAML linenumber. 
        /// 
        LineNumberAndPosition,      // 53

        ///  
        /// Debugging information record that holds the source XAML line position.
        ///  
        LinePosition,               // 54 

        ///  
        /// OptimizedStaticResourceExtension within the header of a deferred section.
        /// 
        OptimizedStaticResource,      // 55
 
        /// 
        /// BamlPropertyRecord that carries an identifier for a StaticResourceExtension 
        /// within the header of a deferred section. 
        /// 
        PropertyWithStaticResourceId, // 56 

        /// 
        /// Placeholder to mark last record
        ///  
        LastRecordType
    } 
 
    /// 
    /// Some attributes have special usages or cause additional actions when they 
    /// are set on an element.  This can be have some other effects
    /// such as setting the xml:lang or xml:space values in the parser context.
    /// The PropertyUsage describes addition effects or usage for this property.
    ///  
    internal enum BamlAttributeUsage : short
    { 
        ///  A regular property that has no other use  
        Default = 0,
 
        ///  A property that has xml:lang information 
        XmlLang,

        ///  A property that has xml:space information  
        XmlSpace,
 
        ///  A property that has the RuntimeIdProperty information  
        RuntimeName,
    } 

    // This class handles allocation, read and write management of baml records.
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlRecordManager 
    {
#if !PBTCOMPILER 
        // Genericaly load and create the proper class.
        // This method assumes the seek pointer has already moved passed the recordType
        // field and is at the RecordSize or record contents (depending on record).
        // This method is used so the caller can first read the type of record, and expects 
        // to get back the entire record, or nothing (for async support).
        internal BamlRecord ReadNextRecord( 
            BinaryReader   bamlBinaryReader, 
            long           bytesAvailable,
            BamlRecordType recordType) 
        {
            BamlRecord bamlRecord; // = null

            // Create the proper BamlRecord based on the recordType.  The assembly, 
            // type and attribute records are created every time, since they are
            // used by the BamlMapTable.  The other records are re-used, so they 
            // are created once and cached. 
            switch(recordType)
            { 
                case BamlRecordType.AssemblyInfo:
                    bamlRecord = new BamlAssemblyInfoRecord();
                    break;
                case BamlRecordType.TypeInfo: 
                    bamlRecord = new BamlTypeInfoRecord();
                    break; 
                case BamlRecordType.TypeSerializerInfo: 
                    bamlRecord = new BamlTypeInfoWithSerializerRecord();
                    break; 
                case BamlRecordType.AttributeInfo:
                    bamlRecord = new BamlAttributeInfoRecord();
                    break;
                case BamlRecordType.StringInfo: 
                    bamlRecord = new BamlStringInfoRecord();
                    break; 
                case BamlRecordType.DefAttributeKeyString: 
                    bamlRecord = new BamlDefAttributeKeyStringRecord();
                    break; 
                case BamlRecordType.DefAttributeKeyType:
                    bamlRecord = new BamlDefAttributeKeyTypeRecord();
                    break;
                case BamlRecordType.KeyElementStart: 
                    bamlRecord = new BamlKeyElementStartRecord();
                    break; 
 
                default:
 
                    // Get the current record from the cache.  If there's nothing there yet,
                    // or if what is there is pinned, then create one.  Note that records in the
                    // read cache are implicitly recycled, and records in the write cache are explicitly
                    // recycled (i.e., there's a ReleaseWriteRecord, but no ReleaseReadRecord). 

                    bamlRecord = _readCache[(int)recordType]; 
                    if (null == bamlRecord || bamlRecord.IsPinned ) 
                    {
                        bamlRecord = _readCache[(int)recordType] = AllocateRecord(recordType); 
                    }

                    break;
            } 

            bamlRecord.Next = null; 
 
            if (null != bamlRecord)
            { 
                // If LoadRecordSize indicates it can determine the record size
                // and has determined that there is enough content to load the
                // entire record, then continue.
                if (bamlRecord.LoadRecordSize(bamlBinaryReader, bytesAvailable) && 
                    bytesAvailable >= bamlRecord.RecordSize)
                { 
                    bamlRecord.LoadRecordData(bamlBinaryReader); 
                }
                else 
                {
                    bamlRecord = null;
                }
            } 

            return bamlRecord; 
        } 

        ///  
        /// Return the object if it should be treated as IAddChild, otherwise return null
        /// 
        static internal IAddChild AsIAddChild(object obj)
        { 
            IAddChild iac = obj as IAddChildInternal;
            return iac; 
        } 
#endif
 
        /// 
        /// True if type should be treated as IAddChild
        /// 
        static internal bool TreatAsIAddChild(Type parentObjectType) 
        {
            return (KnownTypes.Types[(int)KnownElements.IAddChildInternal].IsAssignableFrom( parentObjectType )); 
        } 

        static internal BamlRecordType GetPropertyStartRecordType(Type propertyType, bool propertyCanWrite) 
        {
            BamlRecordType recordType;
            if (propertyType.IsArray)
            { 
                recordType = BamlRecordType.PropertyArrayStart;
            } 
            else if (typeof(IDictionary).IsAssignableFrom(propertyType)) 
            {
                recordType = BamlRecordType.PropertyIDictionaryStart; 
            }
            else if ((typeof(IList).IsAssignableFrom(propertyType) ||
                       BamlRecordManager.TreatAsIAddChild(propertyType) ||
                       (typeof(IEnumerable).IsAssignableFrom(propertyType) && !propertyCanWrite))) 
            {
                // we're a list if: 
                // 1) the property type is an IList. 
                // 2) the property type is an IAddChild (internal).
                // 3) the property type is an IEnumerable and read-only and the parent is an IAddChild (internal). 
                // for the third case, we can't check the parent until run-time.
                recordType = BamlRecordType.PropertyIListStart;
            }
            else 
            {
                recordType = BamlRecordType.PropertyComplexStart; 
            } 

            return recordType; 
        }

        // Helper function to create a BamlRecord from a BamlRecordType
        private BamlRecord AllocateWriteRecord(BamlRecordType recordType) 
        {
            BamlRecord record; 
 
            switch (recordType)
            { 
                case BamlRecordType.PropertyCustom:
                    record = new BamlPropertyCustomWriteInfoRecord();
                    break;
 
                default:
                    record = AllocateRecord(recordType); 
                    break; 
            }
 
            return record;
        }

        // Helper function to create a BamlRecord from a BamlRecordType 
        private BamlRecord AllocateRecord(BamlRecordType recordType)
        { 
            BamlRecord record; 

            switch(recordType) 
            {
                case BamlRecordType.DocumentStart:
                    record = new BamlDocumentStartRecord();
                    break; 
                case BamlRecordType.DocumentEnd:
                    record = new BamlDocumentEndRecord(); 
                    break; 
                case BamlRecordType.ConnectionId:
                    record = new BamlConnectionIdRecord(); 
                    break;
                case BamlRecordType.ElementStart:
                    record = new BamlElementStartRecord();
                    break; 
                case BamlRecordType.ElementEnd:
                    record = new BamlElementEndRecord(); 
                    break; 
                case BamlRecordType.DeferableContentStart:
                    record = new BamlDeferableContentStartRecord(); 
                    break;
                case BamlRecordType.DefAttributeKeyString:
                    record = new BamlDefAttributeKeyStringRecord();
                    break; 
                case BamlRecordType.DefAttributeKeyType:
                    record = new BamlDefAttributeKeyTypeRecord(); 
                    break; 
                case BamlRecordType.LiteralContent:
                    record = new BamlLiteralContentRecord(); 
                    break;
                case BamlRecordType.Property:
                    record = new BamlPropertyRecord();
                    break; 
                case BamlRecordType.PropertyWithConverter:
                    record = new BamlPropertyWithConverterRecord(); 
                    break; 
                case BamlRecordType.PropertyStringReference:
                    record = new BamlPropertyStringReferenceRecord(); 
                    break;
                case BamlRecordType.PropertyTypeReference:
                    record = new BamlPropertyTypeReferenceRecord();
                    break; 
                case BamlRecordType.PropertyWithExtension:
                    record = new BamlPropertyWithExtensionRecord(); 
                    break; 
                case BamlRecordType.PropertyCustom:
                    record = new BamlPropertyCustomRecord(); 
                    break;
                case BamlRecordType.PropertyComplexStart:
                    record = new BamlPropertyComplexStartRecord();
                    break; 
                case BamlRecordType.PropertyComplexEnd:
                    record = new BamlPropertyComplexEndRecord(); 
                    break; 
                case BamlRecordType.RoutedEvent:
                    record = new BamlRoutedEventRecord(); 
                    break;
                case BamlRecordType.PropertyArrayStart:
                    record = new BamlPropertyArrayStartRecord();
                    break; 
                case BamlRecordType.PropertyArrayEnd:
                    record = new BamlPropertyArrayEndRecord(); 
                    break; 
                case BamlRecordType.PropertyIListStart:
                    record = new BamlPropertyIListStartRecord(); 
                    break;
                case BamlRecordType.PropertyIListEnd:
                    record = new BamlPropertyIListEndRecord();
                    break; 
                case BamlRecordType.PropertyIDictionaryStart:
                    record = new BamlPropertyIDictionaryStartRecord(); 
                    break; 
                case BamlRecordType.PropertyIDictionaryEnd:
                    record = new BamlPropertyIDictionaryEndRecord(); 
                    break;
                case BamlRecordType.Text:
                    record = new BamlTextRecord();
                    break; 
                case BamlRecordType.TextWithConverter:
                    record = new BamlTextWithConverterRecord(); 
                    break; 
                case BamlRecordType.TextWithId:
                    record = new BamlTextWithIdRecord(); 
                    break;
                case BamlRecordType.XmlnsProperty:
                    record = new BamlXmlnsPropertyRecord();
                    break; 
                case BamlRecordType.PIMapping:
                    record = new BamlPIMappingRecord(); 
                    break; 
                case BamlRecordType.DefAttribute:
                    record = new BamlDefAttributeRecord(); 
                    break;
                case BamlRecordType.PresentationOptionsAttribute:
                    record = new BamlPresentationOptionsAttributeRecord();
                    break; 
                case BamlRecordType.KeyElementStart:
                    record = new BamlKeyElementStartRecord(); 
                    break; 
                case BamlRecordType.KeyElementEnd:
                    record = new BamlKeyElementEndRecord(); 
                    break;
                case BamlRecordType.ConstructorParametersStart:
                    record = new BamlConstructorParametersStartRecord();
                    break; 
                case BamlRecordType.ConstructorParametersEnd:
                    record = new BamlConstructorParametersEndRecord(); 
                    break; 
                case BamlRecordType.ConstructorParameterType:
                    record = new BamlConstructorParameterTypeRecord(); 
                    break;
                case BamlRecordType.ContentProperty:
                    record = new BamlContentPropertyRecord();
                    break; 
                case BamlRecordType.AssemblyInfo:
                case BamlRecordType.TypeInfo: 
                case BamlRecordType.TypeSerializerInfo: 
                case BamlRecordType.AttributeInfo:
                case BamlRecordType.StringInfo: 
                    Debug.Assert(false,"Assembly, Type and Attribute records are not cached, so don't ask for one.");
                    record = null;
                    break;
                case BamlRecordType.StaticResourceStart: 
                    record = new BamlStaticResourceStartRecord();
                    break; 
                case BamlRecordType.StaticResourceEnd: 
                    record = new BamlStaticResourceEndRecord();
                    break; 
                case BamlRecordType.StaticResourceId:
                    record = new BamlStaticResourceIdRecord();
                    break;
                case BamlRecordType.LineNumberAndPosition: 
                    record = new BamlLineAndPositionRecord();
                    break; 
                case BamlRecordType.LinePosition: 
                    record = new BamlLinePositionRecord();
                    break; 
                case BamlRecordType.OptimizedStaticResource:
                    record = new BamlOptimizedStaticResourceRecord();
                    break;
                case BamlRecordType.PropertyWithStaticResourceId: 
                    record = new BamlPropertyWithStaticResourceIdRecord();
                    break; 
                default: 
                    Debug.Assert(false,"Unknown RecordType");
                    record = null; 
                    break;
            }

            return record; 
        }
 
        // This should only be called from BamlRecordWriter -- it gets a record from the record 
        // cache that must be freed with ReleaseRecord before GetRecord is called again.
        internal BamlRecord GetWriteRecord(BamlRecordType recordType) 
        {
            // Create the cache of records used in writing, on demand

            if( _writeCache == null ) 
            {
                _writeCache = new BamlRecord[(int)BamlRecordType.LastRecordType]; 
            } 

            BamlRecord record = _writeCache[(int)recordType]; 
            if (null == record)
            {
                record = AllocateWriteRecord(recordType);
            } 
            else
            { 
                _writeCache[(int)recordType] = null; 
            }
 
            // It is important to set RecordSize for variable size records
            // to a negative number to indicate that it has not been set yet.
            // Fixed size records should ignore this set.
            record.RecordSize = -1; 
            return record;
        } 
 

        //+--------------------------------------------------------------------------------------------- 
        //
        //  ReleaseWriteRecord
        //
        //  Frees a record originally claimed with GetWriteRecord. Note that records in the 
        //  read cache are implicitly recycled, and records in the write cache are explicitly
        //  recycled (i.e., there's a ReleaseWriteRecord, but no ReleaseReadRecord). 
        // 
        //+---------------------------------------------------------------------------------------------
 
        internal void ReleaseWriteRecord(BamlRecord record)
        {
            // Put the write record back into the cache, if we're allowed to recycle it.
 
            if( !record.IsPinned )
            { 
                Debug.Assert(null == _writeCache[(int)record.RecordType]); 
                if (null != _writeCache[(int)record.RecordType])
                { 
                    // This is really an internal error.
                    throw new InvalidOperationException(SR.Get(SRID.ParserMultiBamls));
                }
                _writeCache[(int)record.RecordType] = record; 
            }
        } 
 

        // Cache of BamlRecords, used during read, to avoid lots of records from being 
        // created.  If a record gets pinned (BamlRecord.IsPinned gets set), it is not re-used.

        #if !PBTCOMPILER
        BamlRecord[] _readCache = new BamlRecord[(int)BamlRecordType.LastRecordType]; 
        #endif
 
        // Cache of BamlRecords, used during write, also to avoid lots of records 
        // from being created.
 
        BamlRecord[] _writeCache = null; //new BamlRecord[(int)BamlRecordType.LastRecordType];

    }
 
    // The base of all baml records.  This gives a fixed size record that contains
    // line number information used for generating error messages.  Note that the 
    // line number information is not currently written out to the baml stream. 
    internal abstract class BamlRecord
    { 

 #region Methods

#if !PBTCOMPILER 
        // If there are enough bytes available, load the record size from the
        // binary reader.  For fixed size records that derive from BamlRecord, 
        // there is no size field in the baml file, so this always succeeds. 
        internal virtual bool LoadRecordSize(
            BinaryReader bamlBinaryReader, 
            long         bytesAvailable)
        {
            return true;
        } 

        // Load record data.  This does not include the record type, or the 
        // size field, which are loaded separately.  If the subclass has no 
        // specific data to load, then don't override this.
        internal virtual void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
        }
#endif
 
        // Writes data at the current position seek pointer points
        // to byte after the end of record when done. 
        internal virtual void Write(BinaryWriter bamlBinaryWriter) 
        {
            // BamlRecords may be used without a stream, so if you attempt to write when there 
            // isn't a writer, just ignore it.
            if (bamlBinaryWriter == null)
            {
                return; 
            }
 
            // Baml records always start with record type 
            bamlBinaryWriter.Write((byte) RecordType);
 
            // IMPORTANT:  The RecordType is the last thing written before calling
            //             WriteRecordData.  Some records assume the record type is located
            //             directly before the current stream location and may change it, so
            //             don't change where the record type is written in the stream!!! 
            //             Paint is one example of a DP object that will seek back to change
            //             the record type if it is unable to serialize itself. 
            WriteRecordData(bamlBinaryWriter); 
        }
 
        // Write contents of the record, excluding size (if any) and record type.
        // If the subclass has no specific data to write out, don't override this.
        internal virtual void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
        }
 
 
#endregion Methods
 
#region Properties

        // Actual size of the complete BamlRecord (excluding RecordType) in bytes.
        // Currently limited to 2 gigabytes.  Default size is 0 bytes of data. 
        // Subclasses must override if they have a different size.
        internal virtual Int32 RecordSize 
        { 
            get { return 0; }
            set { Debug.Assert (value == -1, "Setting fixed record to an invalid size"); } 
        }

        // Identifies the type off BAML record.  This is used when casting to
        // a BamlRecord subclass.  All subclasses **MUST** override this. 
        internal virtual BamlRecordType RecordType
        { 
            get 
            {
                Debug.Assert(false, "Must override RecordType"); 
                return BamlRecordType.Unknown;
            }
        }
 

#if !PBTCOMPILER 
        // Next Record pointer - used in BamlObjectFactory 
        internal BamlRecord Next
        { 
            get { return _nextRecord; }
            set { _nextRecord = value ; }
        }
#endif 

        // The BamlRecorManager keeps a cache of baml records and tries to reuse them automatically. 
        // To keep a record from being cached, it can be pinned.  For correct pinning we keep a 
        // pin count.  To save working set, we only have two bits for the reference count.
        // So if the reference count reaches three the record becomes permanently pinned. 

        internal bool IsPinned
        {
            get 
            {
                return PinnedCount > 0; 
            } 

        } 

        // (See comment on IsPinned.)
        internal int PinnedCount
        { 
            get
            { 
                return _flags[_pinnedFlagSection]; 
            }
 
            set
            {
                Debug.Assert( value <= 3 && value >= 0 );
                _flags[_pinnedFlagSection] = value; 
            }
        } 
 
        // (See comment on IsPinned.)
        internal void Pin() 
        {
            if( PinnedCount < 3 )
            {
                ++PinnedCount; 
            }
        } 
 
#if !PBTCOMPILER
        // (See comment on IsPinned.) 
        internal void Unpin()
        {
            if( PinnedCount < 3 )
            { 
                --PinnedCount;
            } 
        } 
#endif
 


#endregion Properties
 
#region Data
 
        // Internal flags for efficient storage 
        // NOTE: bits here are used by sub-classes also.
        // This BitVector32 field is shared by subclasses to save working set.  Sharing flags like this 
        // is easier in e.g. FrameworkElement, where the class hierarchy is linear, but can be bug-prone otherwise.  To make the
        // code less fragile, each class abstractly provides it's last section to subclasses(LastFlagsSection), which they can
        // use in their call to CreateSection.
 
        internal BitVector32 _flags;
 
        // Allocate space in _flags. 

        private static BitVector32.Section _pinnedFlagSection = BitVector32.CreateSection( 3 /* Allocates two bits to store values up to 3 */ ); 

        // This provides subclasses with a referece section to create their own section.
        internal static BitVector32.Section LastFlagsSection
        { 
            get { return _pinnedFlagSection; }
        } 
 

#if !PBTCOMPILER 
        private BamlRecord _nextRecord = null;
#endif

 
        // Size of the record type field in the baml file.
        internal const int RecordTypeFieldLength = 1; 
 
#if !PBTCOMPILER
        public override string ToString() 
        {
            return string.Format(CultureInfo.InvariantCulture, "{0}", RecordType);
        }
 
        protected static string GetTypeName(int typeId)
        { 
            string typeName = typeId.ToString(CultureInfo.InvariantCulture); 
            if(typeId < 0)
            { 
                KnownElements elm = (KnownElements)(-typeId);
                typeName = elm.ToString();
            }
            return typeName; 
        }
 
 
        // This helper checks for records that indicate that you're out of
        // an element start, and into it's "content" (in the xml sense). 
        // We have to infer this, because unlike Xml, Baml doesn't provide
        // an end-attributes record.

        internal static bool IsContentRecord( BamlRecordType bamlRecordType ) 
        {
            return bamlRecordType == BamlRecordType.PropertyComplexStart 
                   || 
                   bamlRecordType == BamlRecordType.PropertyArrayStart
                   || 
                   bamlRecordType == BamlRecordType.PropertyIListStart
                   ||
                   bamlRecordType == BamlRecordType.PropertyIDictionaryStart
                   || 
                   bamlRecordType == BamlRecordType.Text;
 
        } 

#endif 

#endregion Data
    }
 
    // An abstract base class for records that record their size as part of the
    // baml stream. 
    //  
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal abstract class BamlVariableSizedRecord : BamlRecord
    {
 #region Methods 

#if !PBTCOMPILER 
        // If there are enough bytes available, load the record size from the 
        // binary reader.  The default action is to load the 4 byte size from
        // the reader, if there are at least 4 bytes available. 
        internal override bool LoadRecordSize(
            BinaryReader bamlBinaryReader,
            long         bytesAvailable)
        { 
           int recordSize;
           bool loadedSize = LoadVariableRecordSize(bamlBinaryReader, bytesAvailable, out recordSize); 
           if (loadedSize) 
           {
               RecordSize = recordSize; 
           }
           return loadedSize;
        }
 
        // If there are enough bytes available, load the record size from the
        // binary reader.  The default action is to load the 4 byte size from 
        // the reader, if there are at least 4 bytes available. 
        internal static bool LoadVariableRecordSize(
                BinaryReader bamlBinaryReader, 
                long         bytesAvailable,
            out int          recordSize)
        {
            if (bytesAvailable >= MaxRecordSizeFieldLength) 
            {
                recordSize = ((BamlBinaryReader)bamlBinaryReader).Read7BitEncodedInt(); 
                return true; 
            }
            else 
            {
                recordSize = -1;
                return false;
            } 
        }
#endif 
 
        protected int ComputeSizeOfVariableLengthRecord(long start, long end)
        { 
            int size = (Int32)(end - start);
            int sizeOfSize = BamlBinaryWriter.SizeOf7bitEncodedSize(size);
            sizeOfSize = BamlBinaryWriter.SizeOf7bitEncodedSize(sizeOfSize+size);
            return (sizeOfSize+size); 
        }
 
        // Writes data at the current position seek pointer points 
        // to byte after the end of record when done.
        internal override void Write(BinaryWriter bamlBinaryWriter) 
        {
            // BamlRecords may be used without a stream, so if you attempt to write when there
            // isn't a writer, just ignore it.
            if (bamlBinaryWriter == null) 
            {
                return; 
            } 

 
            // Baml records always start with record type
            bamlBinaryWriter.Write((byte) RecordType);

            // Remember the file location of this baml record.  This 
            // is needed if we have to come back later to update the sync mode.
            // IMPORTANT:  The RecordType is the last thing written before calling 
            //             WriteRecordData.  Some records assume the record type is located 
            //             directly before the current stream location and may change it, so
            //             don't change where the record type is written in the stream!!! 
            //             Paint is one example of a DP object that will seek back to change
            //             the record type if it is unable to serialize itself.

            //  Write just the data, this is just to measure the size. 
            long startSeekPosition = bamlBinaryWriter.Seek(0,SeekOrigin.Current);
            WriteRecordData(bamlBinaryWriter); 
            long endSeekPosition = bamlBinaryWriter.Seek(0,SeekOrigin.Current); 

            Debug.Assert(RecordSize < 0); 
            RecordSize = ComputeSizeOfVariableLengthRecord(startSeekPosition, endSeekPosition);

            // seek back to the begining,  this time write the size, then the data.
            bamlBinaryWriter.Seek((int)startSeekPosition, SeekOrigin.Begin); 
            WriteRecordSize(bamlBinaryWriter);
            WriteRecordData(bamlBinaryWriter); 
        } 

        // Write the size of this record.  The default action is to write the 4 byte 
        // size, which may be overwritten later once WriteRecordData has been called.
        internal void WriteRecordSize(BinaryWriter bamlBinaryWriter)
        {
            ((BamlBinaryWriter)bamlBinaryWriter).Write7BitEncodedInt(RecordSize); 
        }
 
#endregion Methods 

#region Properties 

        // Actual size of the complete BamlRecord in bytes.  Currently
        // limited to 2 gigabytes.
        internal override Int32 RecordSize 
        {
            get { return _recordSize; } 
            set { _recordSize = value; } 
        }
 
        // This provides subclasses with a referece section to create their own section.
        internal new static BitVector32.Section LastFlagsSection
        {
            get { return BamlRecord.LastFlagsSection; } 
        }
 
 
#endregion Properties
 
#region Data

        // Size of the RecordSize field in the baml file.  This must be in
        // sync the type type of _recordSize below. 
        internal const int MaxRecordSizeFieldLength = 4;
 
        Int32          _recordSize = -1;   // we use a 7 bit encoded variable size 

#endregion Data 
    }

    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlXmlnsPropertyRecord : BamlVariableSizedRecord 
    {
 
#region Methods

#if !PBTCOMPILER
        // LoadRecord specific data 
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            Prefix  =  bamlBinaryReader.ReadString(); 
            XmlNamespace  =   bamlBinaryReader.ReadString();
 
            short count = bamlBinaryReader.ReadInt16();

            if (count > 0)
            { 
                AssemblyIds = new short[count];
 
                for (short i = 0; i < count; i++) 
                {
                    AssemblyIds[i] = bamlBinaryReader.ReadInt16(); 
                }
            }
            else
            { 
                AssemblyIds = null;
            } 
 
        }
#endif 

        // write record specific Data.
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            bamlBinaryWriter.Write(Prefix);
            bamlBinaryWriter.Write(XmlNamespace); 
 
            // Write the AssemblyIds which contain XmlnsDefinitionAttribute
            // for this xmlns Uri. 
            // The format should be CountN Id1 Id2 ... IdN
            //
            short count = 0;
 
            if (AssemblyIds != null && AssemblyIds.Length > 0)
            { 
                count = (short) AssemblyIds.Length; 
            }
 
            bamlBinaryWriter.Write(count);

            if (count > 0)
            { 
                for (short i = 0; i < count; i++)
                { 
                    bamlBinaryWriter.Write(AssemblyIds[i]); 
                }
            } 
        }

#endregion Methods
 
#region Properties
 
        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.XmlnsProperty; } 
        }

        internal string Prefix
        { 
            get { return _prefix; }
            set {_prefix = value; } 
        } 

        internal string XmlNamespace 
        {
            get { return _xmlNamespace; }
            set { _xmlNamespace = value; }
        } 

        internal short[] AssemblyIds 
        { 
            get { return _assemblyIds; }
            set { _assemblyIds = value; } 
        }

#endregion Properties
 
#region Data
 
        string _prefix; 
        string _xmlNamespace;
        short[] _assemblyIds; 

#endregion Data

    } 

    //  
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlPIMappingRecord : BamlVariableSizedRecord
    {

#region Methods 

#if !PBTCOMPILER 
        // LoadRecord specific data 
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            XmlNamespace  =  bamlBinaryReader.ReadString();
            ClrNamespace  =  bamlBinaryReader.ReadString();
            AssemblyId    =  bamlBinaryReader.ReadInt16();
        } 
#endif
        // write record specific Data. 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            // write out an int for record size but we'll go back and fill 
            bamlBinaryWriter.Write(XmlNamespace);
            bamlBinaryWriter.Write(ClrNamespace);
            bamlBinaryWriter.Write(AssemblyId);
        } 

#endregion Methods 
 
#region Properties
 
        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.PIMapping; }
        } 

        internal string XmlNamespace 
        { 
            get { return _xmlns; }
            set {_xmlns = value; } 
        }

        internal string ClrNamespace
        { 
            get { return _clrns; }
            set { _clrns = value; } 
        } 

        internal short AssemblyId 
        {

            get
            { 
                short value = (short) _flags[_assemblyIdLowSection];
                value |= (short) (_flags[_assemblyIdHighSection] << 8); 
 
                return value;
            } 

            set
            {
                _flags[_assemblyIdLowSection] = (short)  (value & 0xff); 
                _flags[_assemblyIdHighSection] = (short) ((value & 0xff00) >> 8);
            } 
 
        }
 
        // Allocate space in _flags.
        // BitVector32 doesn't support 16 bit sections, so we have to break
        // it up into 2 sections.
 
        private static BitVector32.Section _assemblyIdLowSection
            = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); 
 
        private static BitVector32.Section _assemblyIdHighSection
            = BitVector32.CreateSection( (short)0xff, _assemblyIdLowSection ); 

#if !PBTCOMPILER
        // This provides subclasses with a referece section to create their own section.
        internal new static BitVector32.Section LastFlagsSection 
        {
            get { return _assemblyIdHighSection; } 
        } 
#endif
 


#endregion Properties
 
#region Data
        string _xmlns; 
        string _clrns; 
#endregion Data
 
    }

    // Common base class for variables sized records that contain a string value
    //  
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    //  
    internal abstract class BamlStringValueRecord : BamlVariableSizedRecord
    { 

#region Methods

#if !PBTCOMPILER 
        // LoadRecord specific data
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        { 
            Value  =  bamlBinaryReader.ReadString();
        } 
#endif

        // write record specific Data.
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(Value); 
        } 

#endregion Methods 

#region Properties

        internal string Value 
        {
            get { return _value; } 
            set { _value = value; } 
        }
 
#endregion Properties

#region Data
        string _value; 
#endregion Data
 
    } 

    // Common methods for baml records that serve as keys in a dictionary. 
    internal interface IBamlDictionaryKey
    {
        // Update the pointer to the Value that was written out when WriteRecordData
        // was first called. 
        void UpdateValuePosition(
            Int32        newPosition, 
            BinaryWriter bamlBinaryWriter); 

        // Relative stream position in the baml stream where the value associated 
        // with this key starts.  It is relative to the end of the keys section,
        // or the start of the values section.
        Int32 ValuePosition { get; set; }
 
        // The actual key object used in the dictionary.  This may be a string,
        // field, type or other object. 
        object KeyObject { get; set; } 

        // Position in the stream where ValuePosition was written.  This is needed 
        // when updating the ValuePosition.
        Int64 ValuePositionPosition { get; set; }

        // True if the value associated with this key is shared. 
        bool Shared { get; set; }
 
        // Whether Shared was set. 
        bool SharedSet { get; set; }
 
#if !PBTCOMPILER
        object[] StaticResourceValues {get; set;}
#endif
    } 

    // Common interface implemented by BamlRecords that 
    // use optimized storage for MarkupExtensions. 
    internal interface IOptimizedMarkupExtension
    { 
        short ExtensionTypeId
        {
            get;
        } 

        short ValueId 
        { 
            get;
        } 

        bool IsValueTypeExtension
        {
            get; 
        }
 
        bool IsValueStaticExtension 
        {
            get; 
        }
    }

    // BamlRecord use in a defer loaded dictionary as the key for adding a value. 
    // The value is a type that is refered to using a TypeID
    //  
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlDefAttributeKeyTypeRecord : BamlElementStartRecord, IBamlDictionaryKey
    {
        internal BamlDefAttributeKeyTypeRecord()
        { 
            Pin(); // Don't allow this record to be recycled in the read cache.
        } 
 
#region Methods
 
#if !PBTCOMPILER
        // LoadRecord specific data
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            base.LoadRecordData(bamlBinaryReader);
            _valuePosition =  bamlBinaryReader.ReadInt32(); 
            ((IBamlDictionaryKey)this).Shared = bamlBinaryReader.ReadBoolean(); 
            ((IBamlDictionaryKey)this).SharedSet = bamlBinaryReader.ReadBoolean();
        } 
#endif

        // Write record specific Data.
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            base.WriteRecordData(bamlBinaryWriter); 
            _valuePositionPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); 
            bamlBinaryWriter.Write(_valuePosition);
            bamlBinaryWriter.Write(((IBamlDictionaryKey)this).Shared); 
            bamlBinaryWriter.Write(((IBamlDictionaryKey)this).SharedSet);
        }

        // Update the pointer to the Value that was written out when WriteRecordData 
        // was first called.  At that time the true position was probably not known,
        // so it is written out later.  Be certain to leave the passed writer pointing 
        // to the same location it was at when this call was made. 
        void IBamlDictionaryKey.UpdateValuePosition(
            Int32        newPosition, 
            BinaryWriter bamlBinaryWriter)
        {
            Debug.Assert(_valuePositionPosition != -1,
                    "Must call WriteRecordData before updating position"); 

            // Use relative positions to reduce the possibility of truncation, 
            // since Seek takes a 32 bit int, but position is a 64 bit int. 
            Int64 existingPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current);
            Int32 deltaPosition = (Int32)(_valuePositionPosition-existingPosition); 

            bamlBinaryWriter.Seek(deltaPosition, SeekOrigin.Current);
            bamlBinaryWriter.Write(newPosition);
            bamlBinaryWriter.Seek(-ValuePositionSize-deltaPosition, SeekOrigin.Current); 
        }
 
#endregion Methods 

#region Properties 

        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.DefAttributeKeyType; } 
        }
 
        // Relative stream position in the baml stream where the value associated 
        // with this key starts.  It is relative to the end of the keys section,
        // or the start of the values section. 
        Int32 IBamlDictionaryKey.ValuePosition
        {
            get { return _valuePosition; }
            set { _valuePosition = value; } 
        }
 
        // The actual key used in the defer loaded dictionary.  For this type of 
        // record the key is a Type that is obtained at runtime from the base
        // classes TypeId 
        object IBamlDictionaryKey.KeyObject
        {
            get { return _keyObject; }
            set { _keyObject = value; } 
        }
 
        // Position in the stream where ValuePosition was written.  This is needed 
        // when updating the ValuePosition.
        Int64 IBamlDictionaryKey.ValuePositionPosition 
        {
            get { return _valuePositionPosition; }
            set { _valuePositionPosition = value; }
        } 

        // True if the value associated with this key is shared. 
        bool IBamlDictionaryKey.Shared 
        {
            get 
            {
                return _flags[_sharedSection] == 1 ? true : false;
            }
 
            set
            { 
                _flags[_sharedSection] = value ? 1 : 0; 
            }
        } 

        // Whether Shared was set
        bool IBamlDictionaryKey.SharedSet
        { 
            get
            { 
                return _flags[_sharedSetSection] == 1 ? true : false; 
            }
 
            set
            {
                _flags[_sharedSetSection] = value ? 1 : 0;
            } 
        }
 
#if !PBTCOMPILER 
        object[] IBamlDictionaryKey.StaticResourceValues
        { 
            get { return _staticResourceValues; }
            set { _staticResourceValues = value; }
        }
#endif 

 
        // Allocate space in _flags. 

        private static BitVector32.Section _sharedSection 
            = BitVector32.CreateSection( 1, BamlElementStartRecord.LastFlagsSection );

        private static BitVector32.Section _sharedSetSection
            = BitVector32.CreateSection( 1, _sharedSection ); 

#if !PBTCOMPILER 
        // This provides subclasses with a referece section to create their own section. 
        internal new static BitVector32.Section LastFlagsSection
        { 
            get { return _sharedSetSection; }
        }
#endif
 

 
#endregion Properties 

#region Data 

        // Size in bytes of the ValuePosition field written out to baml.  This
        // must be in sync with the size of _valuePosition below.
        internal const Int32 ValuePositionSize = 4; 

        // Relative position in the stream where the value associated with this key starts 
        Int32 _valuePosition; 

        // Position in the stream where ValuePosition was written.  This is needed 
        // when updating the ValuePosition.
        Int64 _valuePositionPosition = -1;

        // Actual object key used by a dictionary.  This is a Type object 
        object _keyObject = null;
 
#if !PBTCOMPILER 
        object[] _staticResourceValues;
#endif 

#endregion Data
    }
 

    // BamlRecord for x:Key attribute when used in a defer loaded dictionary 
    // as the key for adding a value.  The value is stored as a string. 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    // 
    internal class BamlDefAttributeKeyStringRecord : BamlStringValueRecord, IBamlDictionaryKey
    { 
        internal BamlDefAttributeKeyStringRecord()
        { 
            Pin(); // Don't allow this record to be recycled in the read cache. 
        }
 
#region Methods

#if !PBTCOMPILER
        // LoadRecord specific data 
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            ValueId = bamlBinaryReader.ReadInt16(); 
            _valuePosition =  bamlBinaryReader.ReadInt32();
            ((IBamlDictionaryKey)this).Shared = bamlBinaryReader.ReadBoolean(); 
            ((IBamlDictionaryKey)this).SharedSet = bamlBinaryReader.ReadBoolean();
            _keyObject = null;
        }
#endif 

        // Write record specific Data. 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(ValueId); 
            _valuePositionPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current);
            bamlBinaryWriter.Write(_valuePosition);
            bamlBinaryWriter.Write(((IBamlDictionaryKey)this).Shared);
            bamlBinaryWriter.Write(((IBamlDictionaryKey)this).SharedSet); 
        }
 
        // Update the pointer to the Value that was written out when WriteRecordData 
        // was first called.  At that time the true position was probably not known,
        // so it is written out later.  Be certain to leave the passed writer pointing 
        // to the same location it was at when this call was made.
        void IBamlDictionaryKey.UpdateValuePosition(
            Int32        newPosition,
            BinaryWriter bamlBinaryWriter) 
        {
            Debug.Assert(_valuePositionPosition != -1, 
                    "Must call WriteRecordData before updating position"); 

            // Use relative positions to reduce the possibility of truncation, 
            // since Seek takes a 32 bit int, but position is a 64 bit int.
            Int64 existingPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current);
            Int32 deltaPosition = (Int32)(_valuePositionPosition-existingPosition);
 
            bamlBinaryWriter.Seek(deltaPosition, SeekOrigin.Current);
            bamlBinaryWriter.Write(newPosition); 
            bamlBinaryWriter.Seek(-ValuePositionSize-deltaPosition, SeekOrigin.Current); 
        }
 
#endregion Methods

#region Properties
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.DefAttributeKeyString; } 
        }
 
        // Relative stream position in the baml stream where the value associated
        // with this key starts.  It is relative to the end of the keys section,
        // or the start of the values section.
        Int32 IBamlDictionaryKey.ValuePosition 
        {
            get { return _valuePosition; } 
            set { _valuePosition = value; } 
        }
 
        // True if the value associated with this key is shared.
        bool IBamlDictionaryKey.Shared
        {
            get 
            {
                return _flags[_sharedSection] == 1 ? true : false; 
            } 

            set 
            {
                _flags[_sharedSection] = value ? 1 : 0;
            }
 
        }
 
        // Whether Shared was set 
        bool IBamlDictionaryKey.SharedSet
        { 
            get
            {
                return _flags[_sharedSetSection] == 1 ? true : false;
            } 

            set 
            { 
                _flags[_sharedSetSection] = value ? 1 : 0;
            } 

        }

        // Allocate space in _flags. 

        private static BitVector32.Section _sharedSection 
            = BitVector32.CreateSection( 1, BamlStringValueRecord.LastFlagsSection ); 

        private static BitVector32.Section _sharedSetSection 
            = BitVector32.CreateSection( 1,  _sharedSection );

#if !PBTCOMPILER
        // This provides subclasses with a referece section to create their own section. 
        internal new static BitVector32.Section LastFlagsSection
        { 
            get { return _sharedSetSection; } 
        }
#endif 


        // The following are NOT written out to BAML but are cached at runtime
 
        // The string value translated into a key object.  The string may represent
        // a type, field, or other object that can be translated into an object using 
        // using the Mapper. 
        object IBamlDictionaryKey.KeyObject
        { 
            get { return _keyObject; }
            set { _keyObject = value; }
        }
 
        // Position in the stream where ValuePosition was written.  This is needed
        // when updating the ValuePosition. 
        Int64 IBamlDictionaryKey.ValuePositionPosition 
        {
            get { return _valuePositionPosition; } 
            set { _valuePositionPosition = value; }
        }

        internal Int16 ValueId 
        {
            get { return _valueId; } 
            set { _valueId = value; } 
        }
 

#if !PBTCOMPILER
        object[] IBamlDictionaryKey.StaticResourceValues
        { 
            get { return _staticResourceValues; }
            set { _staticResourceValues = value; } 
        } 
#endif
 
#endregion Properties

#region Data
 
        // Size in bytes of the ValuePosition field written out to baml.  This
        // must be in sync with the size of _valuePosition below. 
        internal const Int32 ValuePositionSize = 4; 

        // Relative position in the stream where the value associated with this key starts 
        Int32 _valuePosition;

        // Position in the stream where ValuePosition was written.  This is needed
        // when updating the ValuePosition. 
        Int64 _valuePositionPosition = -1;
 
        // Actual object key used by a dictionary.  This is the Value string 
        // after conversion.
        object _keyObject = null; 

        Int16 _valueId;

#if !PBTCOMPILER 
        object[] _staticResourceValues;
#endif 
 
#endregion Data
    } 

    // BamlRecord for x:Whatever attribute
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlDefAttributeRecord : BamlStringValueRecord 
    {
 
#region Methods

#if !PBTCOMPILER
        // LoadRecord specific data 
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            Value      =  bamlBinaryReader.ReadString(); 
            NameId     =  bamlBinaryReader.ReadInt16();
            Name       =  null; 
        }
#endif

        // write record specific Data. 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            bamlBinaryWriter.Write(Value); 
            bamlBinaryWriter.Write(NameId);
        } 

#endregion Methods

#region Properties 

        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.DefAttribute; }
        } 

        // The following is written out the baml file.

        internal Int16 NameId 
        {
            get { return _nameId; } 
            set { _nameId = value; } 
        }
 
        // The following are cached locally, but not written to baml.

        internal string Name
        { 
#if !PBTCOMPILER
            get { return _name; } 
#endif 
            set { _name = value; }
        } 

        // Some attributes have special usage, such as setting the XmlLang and XmlSpace
        // strings in the parser context.  This is flagged with this property
        internal BamlAttributeUsage AttributeUsage 
        {
#if !PBTCOMPILER 
            get { return _attributeUsage; } 
#endif
            set { _attributeUsage = value; } 
        }

#endregion Properties
 
#if !PBTCOMPILER
        public override string ToString() 
        { 
            return string.Format(CultureInfo.InvariantCulture,
                                 "{0} nameId({1}) is '{2}' usage={3}", 
                                 RecordType, NameId, Name, AttributeUsage);
        }
#endif
 
#region Data
        string _name; 
        Int16  _nameId; 
        BamlAttributeUsage _attributeUsage;
#endregion Data 

    }

    // BamlRecord for PresentationOptions:Whatever attribute 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlPresentationOptionsAttributeRecord : BamlStringValueRecord 
    {

#region Methods
 
#if !PBTCOMPILER
        // LoadRecord specific data 
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            Value      =  bamlBinaryReader.ReadString(); 
            NameId     =  bamlBinaryReader.ReadInt16();
            Name       =  null;
        }
#endif 

        // write record specific Data. 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(Value); 
            bamlBinaryWriter.Write(NameId);
        }

#endregion Methods 

#region Properties 
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.PresentationOptionsAttribute; }
        }

        // The following is written out the baml file. 

        internal Int16 NameId 
        { 
            get { return _nameId; }
            set { _nameId = value; } 
        }

        // The following are cached locally, but not written to baml.
 
        internal string Name
        { 
#if !PBTCOMPILER 
            get { return _name; }
#endif 
            set { _name = value; }
        }

#endregion Properties 

#if !PBTCOMPILER 
        public override string ToString() 
        {
            return string.Format(CultureInfo.InvariantCulture, 
                                 "{0} nameId({1}) is '{2}' ",
                                 RecordType, NameId, Name);
        }
#endif 

#region Data 
        string _name; 
        Int16  _nameId;
#endregion Data 

    }

    // 
    // BamlPropertyComplexStartRecord is for Complex DependencyProperty declarations
    // in markup, where the actual type and value is determined by subsequent records. 
    // 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    // 
    internal class BamlPropertyComplexStartRecord : BamlRecord
    { 

#region Methods 
 
#if !PBTCOMPILER
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            AttributeId   = bamlBinaryReader.ReadInt16();
        }
#endif 

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        { 
            bamlBinaryWriter.Write(AttributeId);
        } 

#endregion Methods

#region Properties 

        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.PropertyComplexStart; }
        } 

        internal short AttributeId
        {
            get { return _attributeId; } 
            set { _attributeId = value; }
        } 
 
        internal override Int32 RecordSize
        { 
            get { return 2; }
            set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); }
        }
 
#endregion Properties
 
#if !PBTCOMPILER 
        public override string ToString()
        { 
            return string.Format(CultureInfo.InvariantCulture,
                                 "{0} attr({1})",
                                 RecordType, _attributeId);
        } 
#endif
 
#region Data 
        short _attributeId = -1;
#endregion Data 

    }

    // 
    // BamlPropertyStringReferenceRecord is for Property values that are written
    // out as references into the string table. 
    // 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    // 
    internal class BamlPropertyStringReferenceRecord : BamlPropertyComplexStartRecord
    { 
        #region Methods
 
#if !PBTCOMPILER 
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            AttributeId = bamlBinaryReader.ReadInt16();
            StringId  = bamlBinaryReader.ReadInt16();
        }
#endif 

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        { 
            bamlBinaryWriter.Write(AttributeId);
            bamlBinaryWriter.Write(StringId); 
        }

        #endregion Methods
 
        #region Properties
 
        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.PropertyStringReference; } 
        }

        internal short StringId
        { 
            get { return _stringId; }
#if !PBTCOMPILER 
            set { _stringId = value; } 
#endif
        } 

        internal override Int32 RecordSize
        {
            get { return 4; } 
            set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); }
        } 
 
        #endregion Properties
 
        #region Data
        short _stringId = 0;

        #endregion Data 
    }
 
    // 
    // BamlPropertyTypeReferenceRecord is for Property values that are written
    // out as references into the type table.  So the property value is a 'Type' object. 
    //
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlPropertyTypeReferenceRecord : BamlPropertyComplexStartRecord 
    { 
        #region Methods
 
#if !PBTCOMPILER
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        {
            AttributeId = bamlBinaryReader.ReadInt16(); 
            TypeId  = bamlBinaryReader.ReadInt16();
        } 
#endif 

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(AttributeId);
            bamlBinaryWriter.Write(TypeId);
        } 

        #endregion Methods 
 
        #region Properties
 
        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.PropertyTypeReference; }
        } 

        internal short TypeId 
        { 
            get { return _typeId; }
            set { _typeId = value; } 
        }

        internal override Int32 RecordSize
        { 
            get { return 4; }
            set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } 
        } 

        #endregion Properties 

        #region Data
        short _typeId = 0;
        #endregion Data 
    }
 
    // 
    // BamlPropertyWithConverterRecord information for property with custom type converter
    // 
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code.
    //  
    internal class BamlPropertyWithConverterRecord : BamlPropertyRecord
    { 
        #region Methods 

#if !PBTCOMPILER 
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        {
            base.LoadRecordData(bamlBinaryReader);
            ConverterTypeId  = bamlBinaryReader.ReadInt16(); 
        }
#endif 
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            base.WriteRecordData(bamlBinaryWriter);
            bamlBinaryWriter.Write(ConverterTypeId);
        }
 
        #endregion Methods
 
        #region Properties 

        // The following are stored in the baml stream 

        // ID of this type converter.  Referenced in other baml records where a
        // Type is needed.
        internal short ConverterTypeId 
        {
            get { return _converterTypeId; } 
            set { _converterTypeId = value; } 
        }
 
        // Additional properties not stored in the baml stream

        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.PropertyWithConverter; }
        } 
 
        #endregion Properties
 
        #region Data

        short _converterTypeId = 0;
 
        #endregion Data
    } 
 
    //
    // BamlPropertyRecord is for DependencyProperty values that are written 
    // out as strings.
    //
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlPropertyRecord : BamlStringValueRecord 
    {
 
#region Methods

#if !PBTCOMPILER
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            AttributeId   = bamlBinaryReader.ReadInt16(); 
            Value         = bamlBinaryReader.ReadString(); 
        }
#endif 

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        {
            bamlBinaryWriter.Write(AttributeId); 
            bamlBinaryWriter.Write(Value);
        } 
 
#endregion Methods
 
#region Properties

        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.Property; }
        } 
 
        internal short AttributeId
        { 
            get { return _attributeId; }
            set { _attributeId = value; }
        }
 
#endregion Properties
 
#if !PBTCOMPILER 
        public override string ToString()
        { 
            return string.Format(CultureInfo.InvariantCulture,
                                 "{0} attr({1}) <== '{2}'",
                                 RecordType, _attributeId, Value);
        } 
#endif
 
#region Data 
        short  _attributeId = -1;
#endregion Data 


    }
 
    //
    // BamlPropertyWithExtensionRecord is for property values that are Markup extensions 
    // with a single param member that are written out as attributeIds. 
    //
    //  
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code.
    // 
    internal class BamlPropertyWithExtensionRecord : BamlRecord, IOptimizedMarkupExtension 
    {
        #region Methods 
 
#if !PBTCOMPILER
        internal override void LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            AttributeId = bamlBinaryReader.ReadInt16();
            short extensionTypeId = bamlBinaryReader.ReadInt16();
            ValueId = bamlBinaryReader.ReadInt16(); 

            // The upper 4 bits of the ExtensionTypeId are used as flags 
            _extensionTypeId = (short)(extensionTypeId & ExtensionIdMask); 
            IsValueTypeExtension = (extensionTypeId & TypeExtensionValueMask) == TypeExtensionValueMask;
            IsValueStaticExtension = (extensionTypeId & StaticExtensionValueMask) == StaticExtensionValueMask; 
        }
#endif

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(AttributeId); 
            short extensionTypeId = ExtensionTypeId; 
            if (IsValueTypeExtension)
            { 
                extensionTypeId |= TypeExtensionValueMask;
            }
            else if (IsValueStaticExtension)
            { 
                extensionTypeId |= StaticExtensionValueMask;
            } 
            bamlBinaryWriter.Write(extensionTypeId); 
            bamlBinaryWriter.Write(ValueId);
        } 

        #endregion Methods

        #region Properties 

        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.PropertyWithExtension; }
        } 

        // Id of the property whose value is the simple ME
        internal short AttributeId
        { 
            get { return _attributeId; }
            set { _attributeId = value; } 
        } 

        // KnownElement Id of the MarkupExtension 
        public short ExtensionTypeId
        {
            get { return _extensionTypeId; }
            set 
            {
                // we shouldn't ever be intruding on the flags portion of the ExtensionTypeId 
                Debug.Assert(value <= ExtensionIdMask); 
                _extensionTypeId = value;
            } 
        }

        // For StaticExtension: AttributeId of a member
        // For TemplateBindingExtension: AttributeId of a DependencyProperty 
        // For a DynamicResourceExtension:
        //      StringId if the value is a string 
        //      TypeId if the value is a TypeExtension 
        //      AttributeId of the member if the value is a StaticExtension
        public short ValueId 
        {
            get { return _valueId; }
            set { _valueId = value; }
        } 

        internal override Int32 RecordSize 
        { 
            get { return 6; }
            set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } 
        }

        // For DynamicResourceExtension, if the value is itself a simple TypeExtension
        public bool IsValueTypeExtension 
        {
            get { return _flags[_isValueTypeExtensionSection] == 1 ? true : false; } 
            set { _flags[_isValueTypeExtensionSection] = value ? 1 : 0; } 
        }
 
        // For DynamicResourceExtension, if the value is itself a simple StaticExtension
        public bool IsValueStaticExtension
        {
            get { return _flags[_isValueStaticExtensionSection] == 1 ? true : false; } 
            set { _flags[_isValueStaticExtensionSection] = value ? 1 : 0; }
        } 
 
        // Allocate space in _flags.
        private static BitVector32.Section _isValueTypeExtensionSection 
            = BitVector32.CreateSection(1, BamlRecord.LastFlagsSection);

        private static BitVector32.Section _isValueStaticExtensionSection
            = BitVector32.CreateSection(1, _isValueTypeExtensionSection); 

#if !PBTCOMPILER 
        // This provides subclasses with a referece section to create their own section. 
        internal new static BitVector32.Section LastFlagsSection
        { 
            get { return _isValueStaticExtensionSection; }
        }

        public override string ToString() 
        {
            return string.Format(CultureInfo.InvariantCulture, 
                                 "{0} attr({1}) extn({2}) valueId({3})", 
                                 RecordType, _attributeId, _extensionTypeId, _valueId);
        } 
#endif

        #endregion Properties
 
        #region Data
        short _attributeId = -1; 
        short _extensionTypeId = 0; 
        short _valueId = 0;
 
        private static readonly short ExtensionIdMask = 0x0FFF;
        private static readonly short TypeExtensionValueMask = 0x4000;
        private static readonly short StaticExtensionValueMask = 0x2000;
        #endregion Data 
    }
 
    // 
    // BamlPropertyCustomWriteInfoRecord is for DependencyProperty values that support
    // custom Avalon serialization. The property value objects write directly onto 
    // the BAML stream in whatever format they understand. This record is used only
    // during BAML write time.
    //
    //  
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    //  
    internal class BamlPropertyCustomWriteInfoRecord : BamlPropertyCustomRecord
    { 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        {
            int writePositionStart = (int)bamlBinaryWriter.Seek(0, SeekOrigin.Current);
            short serializerTypeId = SerializerTypeId; 

            bamlBinaryWriter.Write(AttributeId); 
            if (serializerTypeId == (short)KnownElements.DependencyPropertyConverter) 
            {
                // There is no need to actually use a real Converter here since we already have the 
                // DP value as an AttributeInfoId.

                // if ValueMemberName exists then remember that the ValueId is a TypeId of the
                // type that declares ValueMemberName, so that it can be resolved correctly at 
                // load time.
                if (ValueMemberName != null) 
                { 
                    bamlBinaryWriter.Write((short)(serializerTypeId | TypeIdValueMask));
                } 
                else
                {
                    bamlBinaryWriter.Write(serializerTypeId);
                } 

                // if ValueMemberName does not exist, ValueId is a KnownProperty Id 
                // else it is a TypeId of the declaring type. 
                bamlBinaryWriter.Write(ValueId);
 
                // Write out the ValueMemberName if it exists
                if (ValueMemberName != null)
                {
                    bamlBinaryWriter.Write(ValueMemberName); 
                }
 
                return; 
            }
 
            bamlBinaryWriter.Write(serializerTypeId);

            bool converted = false;
 
            // If we have an enum or a bool, do conversion to custom binary data here,
            // since we do not have a serializer associated with these types. 
            if (ValueType != null && ValueType.IsEnum) 
            {
                uint uintValue = 0; 
                string [] enumValues = Value.Split(new Char[] { ',' });

                // if the Enum is a flag, then resolve each flag value in the enum value string.
                foreach (string enumValue in enumValues) 
                {
                    FieldInfo enumField = ValueType.GetField(enumValue.Trim(), BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase); 
                    if (enumField != null) 
                    {
                        // get the raw va;ue of the enum field and convert to a uint. 
                        object rawEnumValue = enumField.GetRawConstantValue();
                        uintValue += (uint)Convert.ChangeType(rawEnumValue, typeof(uint), XamlReaderHelper.EnglishUSCulture);
                        converted = true;
                    } 
                    else
                    { 
                        converted = false; 
                        break;
                    } 
                }

                if (converted)
                { 
                    bamlBinaryWriter.Write(uintValue);
                } 
            } 
            else if (ValueType == typeof(Boolean))
            { 
                TypeConverter boolConverter = TypeDescriptor.GetConverter(typeof(Boolean));
                object convertedValue = boolConverter.ConvertFromString(TypeContext, XamlReaderHelper.EnglishUSCulture, Value);
                bamlBinaryWriter.Write((byte)Convert.ChangeType(convertedValue, typeof(byte), XamlReaderHelper.EnglishUSCulture));
                converted = true; 
            }
            else if (SerializerType == typeof(XamlBrushSerializer)) 
            { 
                XamlSerializer serializer = new XamlBrushSerializer();
 
                // If we custom serialize this particular value at this point, then see
                // if it can convert.
                // NOTE:  This is sensitive to changes in the BamlRecordWriter and
                //        BamlRecordManager code and must be kept in sync with them... 
                converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value);
            } 
            else if (SerializerType == typeof(XamlPoint3DCollectionSerializer)) 
            {
                XamlSerializer serializer = new XamlPoint3DCollectionSerializer(); 

                // If we custom serialize this particular value at this point, then see
                // if it can convert.
                // NOTE:  This is sensitive to changes in the BamlRecordWriter and 
                //        BamlRecordManager code and must be kept in sync with them...
                converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); 
            } 
            else if (SerializerType == typeof(XamlVector3DCollectionSerializer))
            { 
                XamlSerializer serializer = new XamlVector3DCollectionSerializer();

                // If we custom serialize this particular value at this point, then see
                // if it can convert. 
                // NOTE:  This is sensitive to changes in the BamlRecordWriter and
                //        BamlRecordManager code and must be kept in sync with them... 
                converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); 
            }
            else if (SerializerType == typeof(XamlPointCollectionSerializer)) 
            {
                XamlSerializer serializer = new XamlPointCollectionSerializer();

                // If we custom serialize this particular value at this point, then see 
                // if it can convert.
                // NOTE:  This is sensitive to changes in the BamlRecordWriter and 
                //        BamlRecordManager code and must be kept in sync with them... 
                converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value);
            } 
            else if (SerializerType == typeof(XamlInt32CollectionSerializer))
            {
                XamlSerializer serializer = new XamlInt32CollectionSerializer();
 
                // If we custom serialize this particular value at this point, then see
                // if it can convert. 
                // NOTE:  This is sensitive to changes in the BamlRecordWriter and 
                //        BamlRecordManager code and must be kept in sync with them...
                converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); 
            }
            else if (SerializerType == typeof(XamlPathDataSerializer))
            {
                XamlSerializer serializer = new XamlPathDataSerializer(); 

                // If we custom serialize this particular value at this point, then see 
                // if it can convert. 
                // NOTE:  This is sensitive to changes in the BamlRecordWriter and
                //        BamlRecordManager code and must be kept in sync with them... 
                converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value);
            }

            if (!converted) 
            {
                throw new XamlParseException(SR.Get(SRID.ParserBadString, Value, ValueType.Name)); 
            } 
        }
 
        // The KnownProperty Id of the Value, if it is a property and can be converted into one,
        // or the TypeId of the owner of the property value
        internal short ValueId
        { 
            get { return _valueId; }
            set { _valueId = value; } 
        } 

        // If ValueId is a TypeId, then this holds the name of the member. 
        internal string ValueMemberName
        {
            get { return _valueMemberName; }
            set { _valueMemberName = value; } 
        }
 
        // The following properties are NOT written to the BAML stream. 

        // Type of this property 
        internal Type ValueType
        {
            get { return _valueType; }
            set { _valueType = value; } 
        }
 
        // The string Value of the property. 
        internal string Value
        { 
            get { return _value; }
            set { _value = value; }
        }
 
        // Type of the XamlSerializer associated with this property.  Null
        // if this type is custom serialized by the parser itself. 
        internal Type SerializerType 
        {
            get { return _serializerType; } 
            set { _serializerType = value; }
        }

        // Context used for type conversion of built in types. 
        internal ITypeDescriptorContext TypeContext
        { 
            get { return _typeContext; } 
            set { _typeContext = value; }
        } 

        short                  _valueId;
        Type                   _valueType;
        string                 _value; 
        string                 _valueMemberName;
        Type                   _serializerType; 
        ITypeDescriptorContext _typeContext; 
    }
 
    //
    // BamlPropertyCustomRecord is for DependencyProperty values that support
    // custom Avalon serialization. This record is used only during BAML load.
    // The property value objects are read directly from the BAML stream by the 
    // custom binary serializer for the property.
    // 
    //  
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlPropertyCustomRecord : BamlVariableSizedRecord
    {
#region Methods 

#if !PBTCOMPILER 
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            AttributeId      = bamlBinaryReader.ReadInt16(); 
            short serializerTypeId = bamlBinaryReader.ReadInt16();

            IsValueTypeId = (serializerTypeId & TypeIdValueMask) == TypeIdValueMask;
            if (IsValueTypeId) 
            {
                serializerTypeId &= (short)(~TypeIdValueMask); 
            } 

            SerializerTypeId = serializerTypeId; 

            ValueObjectSet  = false;
            IsRawEnumValueSet = false;
            _valueObject = null; 

            // ValueObject and ValueObject are not set until BamlRecordReader.ReadPropertyCustomRecord 
            // because the Mapper is needed for custom DPs 

            // NOTE: above may no longer true, so this could be potentially changed to be in sync with 
            // other record. Needs more investigation.
        }

        // Read the binary data using the passed reader and use that to set the ValueObject. 
        internal object GetCustomValue(BinaryReader reader, Type propertyType, short serializerId, BamlRecordReader bamlRecordReader)
        { 
            Debug.Assert(!ValueObjectSet); 

            // Handle enums and bools here directly. 
            // Otherwise call the known custom serializers directly.
            switch (serializerId)
            {
                case (short)KnownElements.EnumConverter: 

                    uint enumBits; 
                    if (_valueObject == null) 
                    {
                        // if no raw value has been read in yet, read it now 
                        // from the baml stream.
                        enumBits = reader.ReadUInt32();
                    }
                    else 
                    {
                        // raw value has been read in earlier, so try to resolve into 
                        // an actual enum value now. 
                        enumBits = (uint)_valueObject;
                    } 

                    if (propertyType.IsEnum)
                    {
                        // property Type is an enum, so raw value can be resolved now. 
                        _valueObject = Enum.ToObject(propertyType, enumBits);
                        ValueObjectSet = true; 
                        IsRawEnumValueSet = false; 
                    }
                    else 
                    {
                        // property Type is not available yet, so raw value cannot
                        // be resolved now. Store it and try later.
                        _valueObject = enumBits; 
                        ValueObjectSet = false;
                        IsRawEnumValueSet = true; 
                    } 

                    return _valueObject; 

                case (short)KnownElements.BooleanConverter:

                    byte boolByte = reader.ReadByte(); 
                    _valueObject = boolByte == 1;
                    break; 
 
                case (short)KnownElements.XamlBrushSerializer:
 
                    // Don't bother creating a XamlBrushSerializer instance & calling ConvertCustomBinaryToObject
                    // on it since that just calls SCB directly liek below. This saves big on perf.
                    _valueObject = SolidColorBrush.DeserializeFrom(reader, bamlRecordReader.TypeConvertContext);
                    break; 

                case (short)KnownElements.XamlPathDataSerializer: 
 
                    _valueObject = XamlPathDataSerializer.StaticConvertCustomBinaryToObject(reader);
                    break; 

                case (short)KnownElements.XamlPoint3DCollectionSerializer:

                    _valueObject = XamlPoint3DCollectionSerializer.StaticConvertCustomBinaryToObject(reader); 
                    break;
 
                case (short)KnownElements.XamlVector3DCollectionSerializer: 

                    _valueObject = XamlVector3DCollectionSerializer.StaticConvertCustomBinaryToObject(reader); 
                    break;

                case (short)KnownElements.XamlPointCollectionSerializer:
 
                    _valueObject = XamlPointCollectionSerializer.StaticConvertCustomBinaryToObject(reader);
                    break; 
 
                case (short)KnownElements.XamlInt32CollectionSerializer:
 
                    _valueObject = XamlInt32CollectionSerializer.StaticConvertCustomBinaryToObject(reader);
                    break;

                default: 
                    Debug.Assert (false, "Unknown custom serializer");
                    return null; 
            } 

            ValueObjectSet = true; 
            return _valueObject;
        }
#endif
 
#endregion Methods
 
#region Properties 

        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.PropertyCustom; }
        }
 
        internal short AttributeId
        { 
            get { return _attributeId; } 
            set { _attributeId = value; }
        } 

        // ID of this serializer type.  Referenced in other baml records where a
        // Type is needed.
        internal short SerializerTypeId 
        {
            get { return _serializerTypeId; } 
            set { _serializerTypeId = value; } 
        }
 
        // The following properties are NOT written to the BAML stream.

#if !PBTCOMPILER
        // Value of the converted object. 
        internal object ValueObject
        { 
            get { return _valueObject; } 
            set { _valueObject = value; }
        } 

        // Return true if GetCustomValue has been called, indicating that
        // a conversion from binary custom data to a ValueObject has occurred.
        internal bool ValueObjectSet 
        {
            get { return _flags[_isValueSetSection] == 1 ? true : false; } 
            set { _flags[_isValueSetSection] = value ? 1 : 0; } 
        }
 
        internal bool IsValueTypeId
        {
            get { return _flags[_isValueTypeIdSection] == 1 ? true : false; }
            set { _flags[_isValueTypeIdSection] = value ? 1 : 0; } 
        }
 
        // true if only the raw value of enum has been read as it cannot yet be 
        // converted into an enum as the Type is not available yet.
        internal bool IsRawEnumValueSet 
        {
            get { return _flags[_isRawEnumValueSetSection] == 1 ? true : false; }
            set { _flags[_isRawEnumValueSetSection] = value ? 1 : 0; }
        } 

        object _valueObject; 
 
        // Allocate space in _flags.
        private static BitVector32.Section _isValueSetSection 
            = BitVector32.CreateSection(1, BamlVariableSizedRecord.LastFlagsSection);

        // Allocate space in _flags.
        private static BitVector32.Section _isValueTypeIdSection 
            = BitVector32.CreateSection(1, _isValueSetSection);
 
        // Allocate space in _flags. 
        private static BitVector32.Section _isRawEnumValueSetSection
            = BitVector32.CreateSection(1, _isValueTypeIdSection); 

        // This provides subclasses with a referece section to create their own section.
        internal new static BitVector32.Section LastFlagsSection
        { 
            get { return _isRawEnumValueSetSection; }
        } 
#endif 

#endregion Properties 

#region Data

        internal static readonly short TypeIdValueMask = 0x4000; 

        short                  _attributeId = 0; 
        short                  _serializerTypeId = 0; 

#endregion Data 
    }

    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlPropertyArrayEndRecord : BamlRecord 
    {
 
#region Properties

        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.PropertyArrayEnd; }
        } 
 
#endregion Properties
    } 

    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlConstructorParametersStartRecord : BamlRecord 
    { 

#region Properties 

        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.ConstructorParametersStart; } 
        }
 
#endregion Properties 

    } 

    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlConstructorParametersEndRecord : BamlRecord 
    { 

#region Properties 

        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.ConstructorParametersEnd; } 
        }
 
#endregion Properties 

    } 

    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlConstructorParameterTypeRecord : BamlRecord 
    { 
        #region Methods
 
#if !PBTCOMPILER
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        {
            TypeId  = bamlBinaryReader.ReadInt16(); 
        }
#endif 
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            bamlBinaryWriter.Write(TypeId);
        }

        #endregion Methods 

        #region Properties 
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.ConstructorParameterType; }
        }

        internal short TypeId 
        {
            get { return _typeId; } 
            set { _typeId = value; } 
        }
 
        internal override Int32 RecordSize
        {
            get { return 2; }
            set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } 
        }
 
        #endregion Properties 

        #region Data 
        short _typeId = 0;
        #endregion Data
    }
 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlPropertyIListEndRecord : BamlRecord 
    {

#region Properties
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.PropertyIListEnd; } 
        }
 
#endregion Properties

    }
 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlPropertyIDictionaryEndRecord : BamlRecord 
    {

#region Properties
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.PropertyIDictionaryEnd; } 
        }
 
#endregion Properties

    }
 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlPropertyComplexEndRecord : BamlRecord 
    {

#region Properties
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.PropertyComplexEnd; } 
        }
 
#endregion Properties

    }
 

    //  
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlPropertyArrayStartRecord : BamlPropertyComplexStartRecord
    {

#region Properties 

        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.PropertyArrayStart; }
        } 

#endregion Properties

    } 

    //  
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlPropertyIListStartRecord : BamlPropertyComplexStartRecord
    {

#region Properties 

        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.PropertyIListStart; }
        } 

#endregion Properties

    } 

    //  
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlPropertyIDictionaryStartRecord : BamlPropertyComplexStartRecord
    {

#region Properties 

        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.PropertyIDictionaryStart; }
        } 

#endregion Properties

    } 

    //  
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlRoutedEventRecord : BamlStringValueRecord
    {

#region Methods 

#if !PBTCOMPILER 
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            AttributeId   = bamlBinaryReader.ReadInt16(); 
            Value         = bamlBinaryReader.ReadString();
        }
#endif
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            bamlBinaryWriter.Write(AttributeId); 
            bamlBinaryWriter.Write(Value);
        } 

#endregion Methods

#region Properties 

        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.RoutedEvent; }
        } 

        internal short AttributeId
        {
            get { return _attributeId; } 
#if !PBTCOMPILER
            set { _attributeId = value; } 
#endif 
        }
 
#endregion Properties

#region Data
 
        short _attributeId = -1;
 
#endregion Data 
    }
 

    // A section of literal content.
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlLiteralContentRecord : BamlStringValueRecord 
    {
 
#region Methods

#if !PBTCOMPILER
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            Value  =  bamlBinaryReader.ReadString(); 
 
            //
 

            Int32 _lineNumber = bamlBinaryReader.ReadInt32();
            Int32 _linePosition = bamlBinaryReader.ReadInt32();
        } 
#endif
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(Value); 

            //

 
            bamlBinaryWriter.Write((Int32)0);
            bamlBinaryWriter.Write((Int32)0); 
        } 

#endregion Methods 

#region Properties

        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.LiteralContent; } 
        } 

#endregion Properties 

     }

    // An record for the connection id that the (Style)BamlRecordReader uses to 
    // hookup an ID or event on any element in the object tree or Style visual tree.
    //  
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlConnectionIdRecord : BamlRecord
    {
#if !PBTCOMPILER
        internal override void LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            ConnectionId = bamlBinaryReader.ReadInt32(); 
        } 
#endif
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        {
            bamlBinaryWriter.Write(ConnectionId);
        } 

        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.ConnectionId; }
        } 

        // Id of the type of this object
        internal Int32 ConnectionId
        { 
            get { return _connectionId; }
            set { _connectionId = value; } 
        } 

        internal override Int32 RecordSize 
        {
            get { return 4; }
            set { Debug.Assert(value == -1, "Wrong size set for element record"); }
        } 

        Int32 _connectionId = -1; 
    } 

    // An object record in the object tree.  This can be a CLR 
    // object or a DependencyObject.
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlElementStartRecord : BamlRecord 
    { 

#region Methods 

#if !PBTCOMPILER
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            TypeId = bamlBinaryReader.ReadInt16();
            byte flags = bamlBinaryReader.ReadByte(); 
            CreateUsingTypeConverter = (flags & 1) != 0; 
            IsInjected = (flags & 2) != 0;
        } 
#endif

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            bamlBinaryWriter.Write(TypeId);
            byte flags = (byte)((CreateUsingTypeConverter ? 1 : 0) | (IsInjected ? 2 : 0)); 
            bamlBinaryWriter.Write(flags); 
        }
 
#endregion Methods

#region Properties
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.ElementStart; } 
        }
 
        // Id of the type of this object
        internal short TypeId
        {
 
            get
            { 
                short value = (short) _flags[_typeIdLowSection]; 
                value |= (short) (_flags[_typeIdHighSection] << 8);
 
                return value;
            }

            set 
            {
                _flags[_typeIdLowSection] = (short)  (value & 0xff); 
                _flags[_typeIdHighSection] = (short) ((value & 0xff00) >> 8); 
            }
 

        }

        // Whether this object instance is expected to be created via TypeConverter 
        internal bool CreateUsingTypeConverter
        { 
            get 
            {
                return _flags[_useTypeConverter] == 1 ? true : false; 
            }

            set
            { 
                _flags[_useTypeConverter] = value ? 1 : 0;
            } 
        } 

        // Whether this element start record is just an injected tag that should not be processed 
        internal bool IsInjected
        {
            get
            { 
                return _flags[_isInjected] == 1 ? true : false;
            } 
 
            set
            { 
                _flags[_isInjected] = value ? 1 : 0;
            }
        }
 
        internal override Int32 RecordSize
        { 
            get { return 3; } 
            set { Debug.Assert(value == -1, "Wrong size set for element record"); }
        } 

#endregion Properties

#if !PBTCOMPILER 
        public override string ToString()
        { 
            return string.Format(CultureInfo.InvariantCulture, 
                                 "{0} typeId={1}",
                                 RecordType, GetTypeName(TypeId)); 
        }
#endif

 
        // Allocate space in _flags.
        // BitVector32 doesn't support 16 bit sections, so we have to break 
        // it up into 2 sections. 

        private static BitVector32.Section _typeIdLowSection 
            = BitVector32.CreateSection( (short)0xff, BamlRecord.LastFlagsSection );

        private static BitVector32.Section _typeIdHighSection
            = BitVector32.CreateSection( (short)0xff, _typeIdLowSection ); 

        private static BitVector32.Section _useTypeConverter 
            = BitVector32.CreateSection( 1, _typeIdHighSection ); 

        private static BitVector32.Section _isInjected 
            = BitVector32.CreateSection( 1, _useTypeConverter );


        // This provides subclasses with a referece section to create their own section. 
        internal new static BitVector32.Section LastFlagsSection
        { 
            get { return _isInjected; } 
        }
    } 



    //+--------------------------------------------------------------------------------------------------------------- 
    //
    //  BamlNamedElementStartRecord 
    // 
    //  This is a BamlElementStartRecord that also carries an element name.
    // 
    //  This is currently internal, used only for templates.  The original intent for this record was that
    //  it become the new design for named objects; any object with an x:Name set, would have that name
    //  incorporated into the element start record.  But that design did not happen, instead the
    //  property attribute are re-ordered such that the name always immediately follows the element 
    //  start record.  So this should be removed, and the template code updated accordingly.  (And in fact,
    //  the template design should be updated so as not to be reliant on naming, as that is too fragile.) 
    // 
    //+----------------------------------------------------------------------------------------------------------------
#if !PBTCOMPILER 
    internal class BamlNamedElementStartRecord : BamlElementStartRecord
    {

#region Methods 

        #if !PBTCOMPILER 
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            TypeId = bamlBinaryReader.ReadInt16(); 
            RuntimeName = bamlBinaryReader.ReadString();
        }
        #endif
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            bamlBinaryWriter.Write(TypeId); 

            if( RuntimeName != null ) 
            {
                bamlBinaryWriter.Write(RuntimeName);
            }
        } 

#endregion Methods 
 
#region Properties
 
        internal string RuntimeName
        {
            get { return _runtimeName; }
            set { _runtimeName = value; } 
        }
 
        // This flag is used by templates to indicate that an ElementStart 
        // record is for an object that will be a template child.  We had to add
        // this to allow some validation during template application.  This isn't 
        // a good solution, because we shouldn't have this record understanding
        // template children.  But the long-term plan is to break the template design
        // away from a dependence on names, at which point this whole BamlNamedElementStartRecord
        // will go away. 
        private bool _isTemplateChild = false;
        internal bool IsTemplateChild 
        { 
            get { return _isTemplateChild; }
            set { _isTemplateChild = value; } 
        }

#endregion Properties
 

#region Data 
 
        // Id of the type of this object
        string _runtimeName = null; 

#endregion Data
    }
#endif 

    // Marks a block that has deferable content.  This record contains the size 
    // of the deferable section, excluding the start and end records themselves. 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    // 
    internal class BamlDeferableContentStartRecord : BamlRecord
    { 
#region Methods
 
#if !PBTCOMPILER 
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            ContentSize = bamlBinaryReader.ReadInt32();
        }
#endif
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            _contentSizePosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); 
            bamlBinaryWriter.Write(ContentSize);
        } 

        // Update the size of the content contained between the end of the start
        // record and the beginning of the end record.  The size of the content is
        // usually not known when the start record is written out. 
        internal void UpdateContentSize(
            Int32         contentSize, 
            BinaryWriter  bamlBinaryWriter) 
        {
            Debug.Assert(_contentSizePosition != -1, 
                    "Must call WriteRecordData before updating content size");

            // Use relative positions to reduce the possibility of truncation,
            // since Seek takes a 32 bit int, but position is a 64 bit int. 
            Int64 existingPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current);
            Int32 deltaPosition = (Int32)(_contentSizePosition-existingPosition); 
 
            bamlBinaryWriter.Seek(deltaPosition, SeekOrigin.Current);
            bamlBinaryWriter.Write(contentSize); 
            bamlBinaryWriter.Seek((int)(-ContentSizeSize-deltaPosition), SeekOrigin.Current);
        }

 
#endregion Methods
 
#region Properties 

        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.DeferableContentStart; }
        }
 
        internal Int32 ContentSize
        { 
            get { return _contentSize; } 
#if !PBTCOMPILER
            set { _contentSize = value; } 
#endif
        }

        internal override Int32 RecordSize 
        {
            get { return 4; } 
            set { Debug.Assert(value == -1, "Wrong size set for element record"); } 
        }
 
#if !PBTCOMPILER

        /// 
        /// For the case of a ResourceDictionary inside template content, we read 
        /// the dictionary values into a byte array while creating the template
        /// content. Later during template instantiation when the dictionary instance 
        /// is created we use this buffer to create a memory stream so that the 
        /// ResourceDictionary can use it to RealizeDeferredContent. This is required
        /// because at template instantiation time we do not have a stream to work with. 
        /// The reader operates on a linked list of BamlRecords.
        /// 
        internal byte[] ValuesBuffer
        { 
            get { return _valuesBuffer; }
            set { _valuesBuffer = value; } 
        } 
#endif
 
#endregion Properties


#region Data 

        // Size of the ContentSize field written out to the baml stream.  This 
        // must be kept in sync with the size of the _contentSize field. 
        const Int64 ContentSizeSize = 4;
 
        // Size of the content between the end of the start record and the
        // beginning of the end record for this element.
        Int32 _contentSize = - 1;
 
        // Absolute position in the stream where ContentSize is written.
        Int64 _contentSizePosition = -1; 
 
#if !PBTCOMPILER
 
        byte[] _valuesBuffer;

#endif
 
#endregion Data
    } 
 
    //+---------------------------------------------------------------------------------------------------------------
    // 
    //  BamlStaticResourceStartRecord
    //
    //  This record marks the start of a StaticResourceExtension within the header for a deferred section.
    // 
    //+----------------------------------------------------------------------------------------------------------------
 
    internal class BamlStaticResourceStartRecord : BamlElementStartRecord 
    {
 
#region Properties

        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.StaticResourceStart; }
        } 
 
#endregion Properties
 
    }

    //+----------------------------------------------------------------------------------------------------------------
    // 
    //  BamlStaticResourceEndRecord
    // 
    //  This record marks the end of a StaticResourceExtension within the header for a deferred section. 
    //
    //+--------------------------------------------------------------------------------------------------------------- 

    internal class BamlStaticResourceEndRecord : BamlElementEndRecord
    {
 
#region Properties
 
        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.StaticResourceEnd; } 
        }

#endregion Properties
 
    }
 
    //+---------------------------------------------------------------------------------------------------------------- 
    //
    //  BamlOptimizedStaticResourceRecord 
    //
    //  This record represents an optimized StaticResourceExtension within the header for a deferred section.
    //
    //+--------------------------------------------------------------------------------------------------------------- 

    internal class BamlOptimizedStaticResourceRecord : BamlRecord, IOptimizedMarkupExtension 
    { 

#region Methods 

#if !PBTCOMPILER
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            byte flags = bamlBinaryReader.ReadByte();
            ValueId = bamlBinaryReader.ReadInt16(); 
 
            IsValueTypeExtension = (flags & TypeExtensionValueMask) != 0;
            IsValueStaticExtension = (flags & StaticExtensionValueMask) != 0; 
        }
#endif

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            byte flags = 0; 
            if (IsValueTypeExtension) 
            {
                flags |= TypeExtensionValueMask; 
            }
            else if (IsValueStaticExtension)
            {
                flags |= StaticExtensionValueMask; 
            }
            bamlBinaryWriter.Write(flags); 
            bamlBinaryWriter.Write(ValueId); 
        }
 
#endregion Methods

#region Properties
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.OptimizedStaticResource; } 
        }
 
        public short ExtensionTypeId
        {
            get { return (short)KnownElements.StaticResourceExtension; }
        } 

        // StringId if the value is a string 
        // TypeId if the value is a TypeExtension 
        // AttributeId of the member if the value is a StaticExtension
        public short ValueId 
        {
            get { return _valueId; }
            set { _valueId = value; }
        } 

        internal override Int32 RecordSize 
        { 
            get { return 3; }
            set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } 
        }

        // If the value is itself a simple TypeExtension
        public bool IsValueTypeExtension 
        {
            get { return _flags[_isValueTypeExtensionSection] == 1 ? true : false; } 
            set { _flags[_isValueTypeExtensionSection] = value ? 1 : 0; } 
        }
 
        // If the value is itself a simple StaticExtension
        public bool IsValueStaticExtension
        {
            get { return _flags[_isValueStaticExtensionSection] == 1 ? true : false; } 
            set { _flags[_isValueStaticExtensionSection] = value ? 1 : 0; }
        } 
 
#endregion Properties
 
#region Data

        short _valueId = 0;
 
        private static readonly byte TypeExtensionValueMask = 0x01;
        private static readonly byte StaticExtensionValueMask = 0x02; 
 
        // Allocate space in _flags.
        private static BitVector32.Section _isValueTypeExtensionSection 
            = BitVector32.CreateSection(1, BamlRecord.LastFlagsSection);

        private static BitVector32.Section _isValueStaticExtensionSection
            = BitVector32.CreateSection(1, _isValueTypeExtensionSection); 

        // This provides subclasses with a referece section to create their own section. 
        internal new static BitVector32.Section LastFlagsSection 
        {
            get { return _isValueStaticExtensionSection; } 
        }

#if !PBTCOMPILER
        public override string ToString() 
        {
            return string.Format(CultureInfo.InvariantCulture, 
                                 "{0} extn(StaticResourceExtension) valueId({1})", 
                                 RecordType, _valueId);
        } 
#endif

#endregion Data
 

    } 
 
    //+---------------------------------------------------------------------------------------------------------------
    // 
    //  BamlStaticResourceIdRecord
    //
    //  This BamlRecord is an identifier for a StaticResourceExtension within the header for a deferred section.
    // 
    //+---------------------------------------------------------------------------------------------------------------
 
    internal class BamlStaticResourceIdRecord : BamlRecord 
    {
 
#region Methods

#if !PBTCOMPILER
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            StaticResourceId = bamlBinaryReader.ReadInt16(); 
        } 
#endif
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        {
            bamlBinaryWriter.Write(StaticResourceId);
        } 

#endregion Methods 
 
#region Properties
 
        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.StaticResourceId; }
        } 

        internal override Int32 RecordSize 
        { 
            get { return 2; }
            set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } 
        }

        internal short StaticResourceId
        { 
            get { return _staticResourceId; }
            set { _staticResourceId = value; } 
        } 

#endregion Properties 


#region Data
 
        short _staticResourceId = -1;
 
#if !PBTCOMPILER 
        public override string ToString()
        { 
            return string.Format(CultureInfo.InvariantCulture,
                                 "{0} staticResourceId({1})",
                                 RecordType, StaticResourceId);
        } 
#endif
 
 
#endregion Data
 
    }

    //+----------------------------------------------------------------------------------------------------------------
    // 
    //  BamlPropertyWithStaticResourceIdRecord
    // 
    //  This BamlRecord represents a BamlPropertyRecord with a StaticResourceId as place holder for 
    //  a StaticResourceExtension within a deferred section.
    // 
    //+---------------------------------------------------------------------------------------------------------------

    internal class BamlPropertyWithStaticResourceIdRecord : BamlStaticResourceIdRecord
    { 

#region Methods 
 
#if !PBTCOMPILER
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            AttributeId = bamlBinaryReader.ReadInt16();
            StaticResourceId = bamlBinaryReader.ReadInt16();
        } 
#endif
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(AttributeId); 
            bamlBinaryWriter.Write(StaticResourceId);
        }

#endregion Methods 

#region Properties 
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.PropertyWithStaticResourceId; }
        }

        internal override Int32 RecordSize 
        {
            get { return 4; } 
            set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } 
        }
 
        // Id of the property whose value is the simple SR
        internal short AttributeId
        {
            get { return _attributeId; } 
            set { _attributeId = value; }
        } 
 
#endregion Properties
 
#region Data

        short _attributeId = -1;
 
#if !PBTCOMPILER
        public override string ToString() 
        { 
            return string.Format(CultureInfo.InvariantCulture,
                                 "{0} attr({1}) staticResourceId({2})", 
                                 RecordType, AttributeId, StaticResourceId);
        }
#endif
 
#endregion Data
 
    } 

 
    // Text content between the begin and end tag of an element.
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlTextRecord : BamlStringValueRecord 
    { 
#region Properties
 
        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.Text; }
        } 

#endregion Properties 
    } 

    // This is a text record within a [Static/Dynamic]ResourceExtension. 
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code.
    //  
    internal class BamlTextWithIdRecord : BamlTextRecord
    { 
#region Methods 

#if !PBTCOMPILER 
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader)
        {
            ValueId  =  bamlBinaryReader.ReadInt16();
        } 
#endif
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(ValueId); 
        }

#endregion Methods
 
#region Properties
 
        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.TextWithId; } 
        }

        internal Int16 ValueId
        { 
            get { return _valueId; }
            set { _valueId = value; } 
        } 

#endregion Properties 

#region Data
        Int16 _valueId;
#endregion Data 
    }
 
    // Text content between the begin and end tag of an element that will be parsed using a type converter. 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    // 
    internal class BamlTextWithConverterRecord : BamlTextRecord
    { 
#region Methods
 
#if !PBTCOMPILER 
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            base.LoadRecordData(bamlBinaryReader);
            ConverterTypeId  = bamlBinaryReader.ReadInt16();
        }
#endif 

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        { 
            base.WriteRecordData(bamlBinaryWriter);
            bamlBinaryWriter.Write(ConverterTypeId); 
        }

#endregion Methods
 
#region Properties
 
        // The following are stored in the baml stream 

        // ID of this type converter.  Referenced in other baml records where a 
        // Type is needed.
        internal short ConverterTypeId
        {
            get { return _converterTypeId; } 
            set { _converterTypeId = value; }
        } 
 
        // Additional properties not stored in the baml stream
 
        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.TextWithConverter; }
        } 

#endregion Properties 
 
#region Data
 
        short _converterTypeId = 0;

#endregion Data
 
    }
 
    // Marks the start of a Baml document.  This must always be the first 
    // record in a BAML stream.   It contains version information, and other
    // document wide directives. 
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code.
    //  
    internal class BamlDocumentStartRecord : BamlRecord
    { 
#region Methods 

        // Writes data at the current position.  The seek pointer points 
        // to byte after the end of record when done.
        internal override void Write(BinaryWriter bamlBinaryWriter)
        {
            // Remember the file location of this baml record.  This 
            // is needed if we have to come back later to update the sync mode.
            if (FilePos == -1 && bamlBinaryWriter != null) 
            { 
                FilePos = bamlBinaryWriter.Seek(0,SeekOrigin.Current);
            } 

            base.Write(bamlBinaryWriter);
        }
 
        // Adjust seeks pointer to this Record and updates the data.
        // Then sets seek pointer pack to original. 
        // NOTE:  This will ONLY work for file sizes under 2 gig.  This is 
        //        not a problem for current useage, since this is mostly used
        //        when updating LoadAsync attribute on the DocumentStart record, 
        //        which is usually set on the first element in the xaml file.
        internal virtual void UpdateWrite(BinaryWriter bamlBinaryWriter)
        {
            // default implementation, class should override if 
            // wants to optimize to only update dirty data.
            long currentPosiition = bamlBinaryWriter.Seek(0,SeekOrigin.Current); 
 
            // seek to original record position.
 
            Debug.Assert(FilePos != -1,"UpdateWrite called but Write Never was");

            // Note: This only works for files up to 2 gig in length.
            //       This is not a new restriction, but it should be 
            //       fixed to work with larger files...
            bamlBinaryWriter.Seek((int)FilePos,SeekOrigin.Begin); 
            Write(bamlBinaryWriter); 
            bamlBinaryWriter.Seek( (int) currentPosiition,SeekOrigin.Begin);
        } 

#if !PBTCOMPILER
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            LoadAsync =  bamlBinaryReader.ReadBoolean();
            MaxAsyncRecords =  bamlBinaryReader.ReadInt32(); 
            DebugBaml = bamlBinaryReader.ReadBoolean(); 
        }
#endif 

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        {
            bamlBinaryWriter.Write(LoadAsync); 
            bamlBinaryWriter.Write(MaxAsyncRecords);
            bamlBinaryWriter.Write(DebugBaml); 
        } 

#endregion Methods 

#region Properties

        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.DocumentStart; } 
        } 

        internal bool LoadAsync 
        {
            get { return _loadAsync; }
#if !PBTCOMPILER
            set { _loadAsync = value; } 
#endif
        } 
 
        internal int MaxAsyncRecords
        { 
            get { return _maxAsyncRecords; }
            set { _maxAsyncRecords = value; }
        }
 
        // Position in the baml file stream
        internal long FilePos 
        { 
            get { return _filePos; }
            set { _filePos  = value; } 
        }

        // Are there Debug Baml Records in this Baml Stream
        internal bool DebugBaml 
        {
            get { return _debugBaml; } 
            set { _debugBaml  = value; } 
        }
 
#endregion Properties

#region Data
        int         _maxAsyncRecords  = -1; 
        bool        _loadAsync = false;
        long        _filePos = -1; 
        bool        _debugBaml = false; 
#endregion Data
    } 

    // This marks the end tag of an element
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    //  
    internal class BamlElementEndRecord : BamlRecord 
    {
 
#region Properties

        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.ElementEnd; }
        } 
 
#endregion Properties
 
    }

    // This marks the start tag of an element being used as the key for an IDictionary
    internal class BamlKeyElementStartRecord : BamlDefAttributeKeyTypeRecord, IBamlDictionaryKey 
    {
        internal BamlKeyElementStartRecord() 
        { 
            Pin(); // Don't allow this record to be recycled in the read cache.
        } 

#region Properties

        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.KeyElementStart; } 
        } 

#endregion Properties 

    }

    // This marks the end tag of an element being used as the key for an IDictionary 
    internal class BamlKeyElementEndRecord : BamlElementEndRecord
    { 
 
#region Properties
 
        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.KeyElementEnd; }
        } 

#endregion Properties 
 
    }
 
    // This marks the end of the baml stream, or document.
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlDocumentEndRecord : BamlRecord 
    { 

#region Properties 

        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.DocumentEnd; } 
        }
 
#endregion Properties 

    } 

    // The following records are used internally in the baml stream to
    // define attribute (eg - property), type and assembly information
    // for records that follow later on in the stream.  They are never 
    // publically exposed
 
    // Information about an assembly where a type is defined 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    // 
    internal class BamlAssemblyInfoRecord : BamlVariableSizedRecord
    { 
        internal BamlAssemblyInfoRecord()
        { 
            Pin(); // Don't allow this record to be recycled in the read cache. 
            AssemblyId = -1;
        } 

#region Methods

#if !PBTCOMPILER 
        // LoadRecord specific data
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        { 
            AssemblyId       =  bamlBinaryReader.ReadInt16();
            AssemblyFullName =  bamlBinaryReader.ReadString(); 
        }
#endif

        // write record specific Data. 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            // write out an int for record size but we'll go back and fill 
            bamlBinaryWriter.Write(AssemblyId);
            bamlBinaryWriter.Write(AssemblyFullName); 
        }

#endregion Methods
 
#region Properties
 
        // The following are stored in the baml stream 

        // ID of this assembly 
        internal short AssemblyId
        {

            get 
            {
                short value = (short) _flags[_assemblyIdLowSection]; 
                value |= (short) (_flags[_assemblyIdHighSection] << 8); 

                return value; 
            }

            set
            { 
                _flags[_assemblyIdLowSection] = (short)  (value & 0xff);
                _flags[_assemblyIdHighSection] = (short) ((value & 0xff00) >> 8); 
            } 

        } 

        // Allocate space in _flags.
        // BitVector32 doesn't support 16 bit sections, so we have to break
        // it up into 2 sections. 

        private static BitVector32.Section _assemblyIdLowSection 
            = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); 

        private static BitVector32.Section _assemblyIdHighSection 
            = BitVector32.CreateSection( (short)0xff, _assemblyIdLowSection );

#if !PBTCOMPILER
        // This provides subclasses with a referece section to create their own section. 
        internal new static BitVector32.Section LastFlagsSection
        { 
            get { return _assemblyIdHighSection; } 
        }
#endif 

        // Full name of this assembly, excluding any suffix.  This has
        // the format "AssemblyName, Version, Culture, PublicKeyToken" when we
        // have a true full name.  Sometimes we aren't given the full assembly 
        // name, in which case the full name is the same as the short name.
        internal string AssemblyFullName 
        { 
            get { return _assemblyFullName; }
            set { _assemblyFullName = value; } 
        }

        // The following are not part of the BAML stream
 
        // Identify type of record
        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.AssemblyInfo; }
        } 

        // The actual loaded assembly
        internal Assembly Assembly
        { 
            get { return _assembly; }
            set { _assembly = value; } 
        } 

 
#endregion Properties


#region Data 

        string   _assemblyFullName; 
        Assembly _assembly; 

#endregion Data 
    }

    // Information about a type for an element, object or property
    //  
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    //  
    internal class BamlTypeInfoRecord : BamlVariableSizedRecord
    { 
        internal BamlTypeInfoRecord()
        {
            Pin(); // Don't allow this record to be recycled in the read cache.
            TypeId = -1; 
        }
 
#region Methods 

#if !PBTCOMPILER 
        // LoadRecord specific data
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader)
        {
            TypeId       =   bamlBinaryReader.ReadInt16(); 
            AssemblyId   =   bamlBinaryReader.ReadInt16();
            TypeFullName =   bamlBinaryReader.ReadString(); 
 
            // Note that the upper 4 bits of the AssemblyId are used for flags
            _typeInfoFlags = (TypeInfoFlags)(AssemblyId >> 12); 
            _assemblyId &= 0x0FFF;
        }
#endif
 
        // write record specific Data.
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        { 
            // write out an int for record size but we'll go back and fill
            bamlBinaryWriter.Write(TypeId); 
            // Note that the upper 4 bits of the AssemblyId are used for flags
            bamlBinaryWriter.Write((short)(((ushort)AssemblyId) | (((ushort)_typeInfoFlags) << 12)));
            bamlBinaryWriter.Write(TypeFullName);
        } 

#endregion Methods 
 
#region Properties
 
        // The following are stored in the baml stream

        // ID of this type.  Refenced in other baml records where a
        // Type is needed. 
        internal short TypeId
        { 
 
            get
            { 
                short value = (short) _flags[_typeIdLowSection];
                value |= (short) (_flags[_typeIdHighSection] << 8);

                return value; 
            }
 
            set 
            {
                _flags[_typeIdLowSection] = (short)  (value & 0xff); 
                _flags[_typeIdHighSection] = (short) ((value & 0xff00) >> 8);
            }

 
        }
 
        // Assembly id of the assembly where this type is defined. 
        // NOTE:  This is always positive in BAML files, but can be set
        //        to -1 for known types when created programmatically. 
        internal short AssemblyId
        {
            get { return _assemblyId; }
            set 
            {
                // Make sure we don't intrude on the Flags portion of the assembly ID 
                if (_assemblyId > 0x0FFF) 
                {
                    throw new XamlParseException(SR.Get(SRID.ParserTooManyAssemblies)); 
                }
                _assemblyId = value;
            }
        } 

        // Fully qualified name of type, including namespace 
        internal string TypeFullName 
        {
            get { return _typeFullName; } 
            set { _typeFullName = value; }
        }

        // Additional properties not stored in the baml stream 

        internal override BamlRecordType RecordType 
        { 
            get { return BamlRecordType.TypeInfo; }
        } 

#if !PBTCOMPILER
        // Actual type.  Filled in here when xaml is used to create
        // a tree, and the token reader knows the type 
        internal Type Type
        { 
            get { return _type; } 
            set { _type = value; }
        } 

        // Extract the namespace from the type full name and return
        // it.  We are assuming here that the type full name has a single
        // classname at the end and we are not refering to a nested class... 
        internal string ClrNamespace
        { 
            get 
            {
                int periodIndex = _typeFullName.LastIndexOf('.'); 
                return periodIndex > 0 ?
                            _typeFullName.Substring(0, periodIndex) :
                            string.Empty;
            } 
        }
#endif 
 
        // True if there is a serializer associated with this type
        internal virtual bool HasSerializer 
        {
            get { return false; }
        }
 
        internal bool IsInternalType
        { 
#if !PBTCOMPILER 
            get
            { 
                return ((_typeInfoFlags & TypeInfoFlags.Internal) == TypeInfoFlags.Internal);
            }
#endif
 
            set
            { 
                // Don't allow resetting to false (i.e. converting back top public if 
                // it becomes non-public, for added safety.
                if (value) 
                {
                    _typeInfoFlags |= TypeInfoFlags.Internal;
                }
            } 
        }
 
#endregion Properties 

#region Data 

        // Allocate space in _flags.
        // BitVector32 doesn't support 16 bit sections, so we have to break
        // it up into 2 sections. 

        private static BitVector32.Section _typeIdLowSection 
            = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); 

        private static BitVector32.Section _typeIdHighSection 
            = BitVector32.CreateSection( (short)0xff, _typeIdLowSection );

#if !PBTCOMPILER
        // This provides subclasses with a referece section to create their own section. 
        internal new static BitVector32.Section LastFlagsSection
        { 
            get { return _typeIdHighSection; } 
        }
#endif 


        // Flags contained in TypeInfo that give additional information
        // about the type that is determined at compile time. 
        [Flags]
        private enum TypeInfoFlags : byte 
        { 
            Internal             = 0x1,
            UnusedTwo            = 0x2, 
            UnusedThree          = 0x4,
        }

        TypeInfoFlags _typeInfoFlags = 0; 
        short         _assemblyId = -1;
        string        _typeFullName; 
#if !PBTCOMPILER 
        Type          _type;
#endif 

#endregion Data

 
    }
 
    // Type info record for a type that has a custom serializer associated with it. 
    // This gives the serializer type that will be used when deserializing this type
    //  
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code.
    // 
    internal class BamlTypeInfoWithSerializerRecord : BamlTypeInfoRecord 
    {
        internal BamlTypeInfoWithSerializerRecord() 
        { 
            Pin(); // Don't allow this record to be recycled in the read cache.
        } 

#region Methods

#if !PBTCOMPILER 
        // LoadRecord specific data
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        { 
            base.LoadRecordData(bamlBinaryReader);
            SerializerTypeId  =   bamlBinaryReader.ReadInt16(); 
        }
#endif

        // write record specific Data. 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            base.WriteRecordData(bamlBinaryWriter); 
            bamlBinaryWriter.Write(SerializerTypeId);
        } 


#endregion Methods
 
#region Properties
 
        // The following are stored in the baml stream 

        // ID of this type.  Refenced in other baml records where a 
        // Type is needed.
        internal short SerializerTypeId
        {
            get { return _serializerTypeId; } 
            set { _serializerTypeId = value; }
        } 
 
        // Additional properties not stored in the baml stream
 
        internal override BamlRecordType RecordType
        {
            get { return BamlRecordType.TypeSerializerInfo; }
        } 

#if !PBTCOMPILER 
        // Actual type of associated serializer.  Filled in here when xaml is used to create 
        // a tree, and the token reader knows the type of the serializer, or
        // when we are reading the baml file and have determined the 
        // serializer type.
        internal Type SerializerType
        {
            get { return _serializerType; } 
            set { _serializerType = value; }
        } 
#endif 

        // True if there is a serializer associated with this type.  A serializer 
        // will never be the first type object in a baml file, so its type ID will
        // never be 0.  Any other ID indicates we have a serializer.
        internal override bool HasSerializer
        { 
            get
            { 
                Debug.Assert( SerializerTypeId != 0 ); 
                return true;
            } 
        }

#endregion Properties
 
#region Data
 
        short _serializerTypeId = 0; 
#if !PBTCOMPILER
        Type _serializerType; 
#endif

#endregion Data
 
    }
 
    // Used for mapping properties and events to an owner type, given the 
    // name of the attribute.  Note that Attribute is used for historical
    // reasons and for similarities to Xml attributes.  For us attributes 
    // are just properties and events.
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlAttributeInfoRecord : BamlVariableSizedRecord 
    { 
        internal BamlAttributeInfoRecord()
        { 
            Pin(); // Don't allow this record to be recycled in the read cache.
            AttributeUsage = BamlAttributeUsage.Default;
        }
 
#region Methods
 
#if !PBTCOMPILER 
        // LoadRecord specific data
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            AttributeId  =   bamlBinaryReader.ReadInt16();
            OwnerTypeId  =   bamlBinaryReader.ReadInt16();
            AttributeUsage = (BamlAttributeUsage)bamlBinaryReader.ReadByte(); 
            Name  =          bamlBinaryReader.ReadString();
        } 
#endif 

        // write record specific Data. 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        {
            // write out an int for record size but we'll go back and fill
            bamlBinaryWriter.Write(AttributeId); 
            bamlBinaryWriter.Write(OwnerTypeId);
            bamlBinaryWriter.Write((Byte)AttributeUsage); 
            bamlBinaryWriter.Write(Name); 
        }
 

#endregion Methods

#region Properties 

        // The following 3 properties are stored in the Baml file and are read and 
        // written by the BamlRecordReader and BamlXamlNodeWriter 

        internal short OwnerTypeId 
        {
            get { return _ownerId; }
            set { _ownerId = value; }
        } 

        internal short AttributeId 
        { 
            set { _attributeId = value; }
            get { return _attributeId; } 
        }

        internal string Name
        { 
            get { return _name; }
            set { _name = value; } 
        } 

        // The following properties are derived at runtime from the above 3 properties using 
        // the Mapper.  Which are set depends on the attribute and the context in which it is
        // used.

        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.AttributeInfo; } 
        } 

#if !PBTCOMPILER 
        // Return type of property.  Note that this uses the same logic as
        // Mapper.GetPropertyType but uses the cached values of DP, PropInfo
        // and AttachedPropertySetter.
        internal Type GetPropertyType() 
        {
            Type validType = null; 
            DependencyProperty dp = DP; 
            if (dp == null)
            { 
                MethodInfo methodInfo = AttachedPropertySetter;
                if (methodInfo == null)
                {
                    PropertyInfo propInfo = PropInfo; 
                    validType = propInfo.PropertyType;
                } 
                else 
                {
                    ParameterInfo[] paramInfo = methodInfo.GetParameters(); 
                    validType = paramInfo[1].ParameterType;
                }
            }
            else 
            {
                validType = dp.PropertyType; 
            } 
            return validType;
        } 
#endif

        /// 
        /// Set the PropertyMember, which can is assumed to be a MethodInfo for 
        /// the static setter method for a DP or a PropertyInfo for the clr property
        ///  
        ///  
        /// The possibility of having multiple member info cached for an attribute is when a
        /// dependency property that does not belong to the default namespace is used in once 
        /// in a once with a namespace prefix and once without it. When it has a namespace
        /// prefix we correctly find the dependency property for it. However when it does not
        /// have a namespace prefix it the parser tries to look it up in the default namespace
        /// and falls back to using the clr wrapper's property info for it instead. Another 
        /// scenario that requires caching more than one property info is when a dependency
        /// property has both a static settor and a clr wrapper. 
        ///  
        internal void SetPropertyMember (object propertyMember)
        { 
            Debug.Assert((propertyMember is MethodInfo) || (propertyMember is PropertyInfo)
                        || (KnownTypes.Types[(int)KnownElements.DependencyProperty].IsAssignableFrom(propertyMember.GetType())),
                "Cache can hold either a MethodInfo and/or a PropertyInfo and/or a DependencyProperty for a given attribute");
 
            if (PropertyMember == null)
            { 
                PropertyMember = propertyMember; 
            }
            else 
            {
                // Cache a additional MemberInfo for the given attribute
                object[] arr = PropertyMember as object[];
                if (arr == null) 
                {
                    arr = new object[3]; 
                    arr[0] = PropertyMember; 
                    arr[1] = propertyMember;
                } 
                else
                {
                    Debug.Assert(arr.Length == 3 && arr[0] != null && arr[1] != null);
                    arr[2] = propertyMember; 
                }
            } 
        } 

        ///  
        /// Return the PropertyMember, which can is assumed to be a MethodInfo for
        /// the static setter method for a DP or a PropertyInfo for the clr property
        /// 
        ///  
        /// The possibility of having multiple member info cached for an attribute is when a
        /// dependency property that does not belong to the default namespace is used in once 
        /// in a once with a namespace prefix and once without it. When it has a namespace 
        /// prefix we correctly find the dependency property for it. However when it does not
        /// have a namespace prefix it the parser tries to look it up in the default namespace 
        /// and falls back to using the clr wrapper's property info for it instead. Another
        /// scenario that requires caching more than one property info is when a dependency
        /// property has both a static settor and a clr wrapper.
        ///  
        internal object GetPropertyMember(bool onlyPropInfo)
        { 
            if (PropertyMember == null || 
                PropertyMember is MemberInfo ||
                KnownTypes.Types[(int)KnownElements.DependencyProperty].IsAssignableFrom(PropertyMember.GetType( )) ) 
            {
                if (onlyPropInfo)
                {
#if PBTCOMPILER 
                    return PropertyMember as PropertyInfo;
#else 
                    return PropInfo; 
#endif
                } 
                else
                {
                    return PropertyMember;
                } 
            }
            else 
            { 
                // The attribute has multiple member info. Choose which one to return.
                object[] arr = (object[])PropertyMember; 
                Debug.Assert(arr.Length == 3 && arr[0] != null && arr[1] != null);

                // If someone queries any MemberInfo for the given attribute then we return the
                // first member info cached for it. If they are looking specifically for a 
                // PropertyInfo we try and find them one.
                if (onlyPropInfo) 
                { 
                    if (arr[0] is PropertyInfo)
                    { 
                        return (PropertyInfo)arr[0];
                    }
                    else if (arr[1] is PropertyInfo)
                    { 
                        return (PropertyInfo)arr[1];
                    } 
                    else 
                    {
                        return arr[2] as PropertyInfo; 
                    }
                }
                else
                { 
                    return arr[0];
                } 
            } 
        }
 
        // Cached value of the DependencyProperty, MethodInfo for the static setter
        // method, or the PropertyInfo for a given property.  If this is an
        // event, then this is null.
        internal object PropertyMember 
        {
            get { return _dpOrMiOrPi; } 
            set { _dpOrMiOrPi = value; } 
        }
 
#if !PBTCOMPILER

        // The cached type of the owner or declarer of this property
        internal Type OwnerType 
        {
            get { return _ownerType; } 
            set { _ownerType = value; } 
        }
 
        // Cached value of the routed event id, if this attribute is for a
        // routed event.  If not a routed event, this is null.
        internal RoutedEvent Event
        { 
            get {  return _Event; }
            set { _Event = value; } 
        } 

        // Cached value of DP, if available 
        internal DependencyProperty DP
        {
            get
            { 
                if (null != _dp)
                    return _dp; 
                else 
                    return _dpOrMiOrPi as DependencyProperty;
            } 
            set
            {
                _dp = value;
                if (_dp != null) 
                {
                    // Release the other copy of the string 
                    _name = _dp.Name; 
                }
            } 
        }

        // Cached value of static property setter method info, if available
        internal MethodInfo AttachedPropertySetter 
        {
            get 
            { 
                return _smi;
            } 

            set
            {
                _smi = value; 
            }
        } 
 
        // Cached value of static property getter method info, if available
        internal MethodInfo AttachedPropertyGetter 
        {
            get
            {
                return _gmi; 
            }
 
            set 
            {
                _gmi = value; 
            }
        }

        // Cached value of EventInfo, if available 
        internal EventInfo EventInfo
        { 
            get { return _ei; } 
            set { _ei = value; }
        } 

        // Cached value of PropertyInfo, if available
        internal PropertyInfo PropInfo
        { 
            get
            { 
                return _pi; 
            }
            set { _pi = value; } 
        }

        internal bool IsInternal
        { 
            get
            { 
                return _flags[_isInternalSection] == 1 ? true : false; 
            }
 
            set
            {
                _flags[_isInternalSection] = value ? 1 : 0;
            } 
        }
#endif 
 
        // Some attributes have special usage, such as setting the XmlLang and XmlSpace
        // strings in the parser context.  This is flagged with this property 
        internal BamlAttributeUsage AttributeUsage
        {
            get
            { 
                return (BamlAttributeUsage) _flags[_attributeUsageSection];
            } 
 
            set
            { 
                _flags[_attributeUsageSection] = (int) value;
            }
        }
 

        // Allocate space in _flags. 
 
        private static BitVector32.Section _isInternalSection
            = BitVector32.CreateSection( 1, BamlVariableSizedRecord.LastFlagsSection ); 

        private static BitVector32.Section _attributeUsageSection
            = BitVector32.CreateSection( 3, _isInternalSection );
 
#if !PBTCOMPILER
        // This provides subclasses with a referece section to create their own section. 
        internal new static BitVector32.Section LastFlagsSection 
        {
            get { return _attributeUsageSection; } 
        }
#endif

#endregion Properties 

#if !PBTCOMPILER 
        public override string ToString() 
        {
            return string.Format(CultureInfo.InvariantCulture, 
                                 "{0} owner={1} attr({2}) is '{3}'",
                                 RecordType, GetTypeName(OwnerTypeId), AttributeId, _name);
        }
#endif 

#region Data 
 
        short _ownerId;
        short _attributeId; 
        string _name;

#if !PBTCOMPILER
        Type               _ownerType = null; 
        RoutedEvent        _Event = null;
        DependencyProperty _dp = null; 
        EventInfo          _ei = null; 
        PropertyInfo       _pi = null;
        MethodInfo         _smi = null; 
        MethodInfo         _gmi = null;
#endif

        object             _dpOrMiOrPi = null;   // MethodInfo, PropertyInfo or DependencyProperty 

#endregion Data 
    } 

    // Information about a String that is an entry in the String table. 
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code.
    //  
    internal class BamlStringInfoRecord : BamlVariableSizedRecord
    { 
        internal BamlStringInfoRecord() 
        {
            Pin(); // Don't allow this record to be recycled in the read cache. 
            StringId = -1;
        }

#region Methods 

#if !PBTCOMPILER 
        // LoadRecord specific data 
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            StringId = bamlBinaryReader.ReadInt16();
            Value    = bamlBinaryReader.ReadString();
        }
#endif 

        // write record specific Data. 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            // write out an int for string Id 
            bamlBinaryWriter.Write(StringId);
            bamlBinaryWriter.Write(Value);
        }
 
#endregion Methods
 
#region Properties 
        // Resource Identifier pointing to the StringTable Entry
        internal short StringId 
        {
            get
            {
                short value = (short) _flags[_stringIdLowSection]; 
                value |= (short) (_flags[_stringIdHighSection] << 8);
 
                return value; 
            }
 
            set
            {
                _flags[_stringIdLowSection] = (short)  (value & 0xff);
                _flags[_stringIdHighSection] = (short) ((value & 0xff00) >> 8); 
            }
        } 
 
        // Resource String
        internal string Value 
        {
            get { return _value; }
            set { _value = value; }
        } 

        // Additional properties not stored in the baml stream 
        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.StringInfo; } 
        }

        // True if there is a serializer associated with this type
        internal virtual bool HasSerializer 
        {
            get { return false; } 
        } 
#endregion Properties
 
#if !PBTCOMPILER
        public override string ToString()
        {
            return string.Format(CultureInfo.InvariantCulture, 
                                 "{0} stringId({1}='{2}'",
                                 RecordType, StringId, _value); 
        } 
#endif
 
#region Data


        // Allocate space in _flags. 
        // BitVector32 doesn't support 16 bit sections, so we have to break
        // it up into 2 sections. 
 
        private static BitVector32.Section _stringIdLowSection
            = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); 

        private static BitVector32.Section _stringIdHighSection
            = BitVector32.CreateSection( (short)0xff, _stringIdLowSection );
 
#if !PBTCOMPILER
        // This provides subclasses with a referece section to create their own section. 
        internal new static BitVector32.Section LastFlagsSection 
        {
            get { return _stringIdHighSection; } 
        }
#endif

        string _value ; 
#endregion Data
    } 
 
    // Sets the content property context for an element
    //  
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code.
    // 
    internal class BamlContentPropertyRecord : BamlRecord 
    {
        #region Methods 
 
#if !PBTCOMPILER
        // LoadRecord specific data 
        internal override void LoadRecordData(BinaryReader bamlBinaryReader)
        {
            AttributeId = bamlBinaryReader.ReadInt16();
        } 
#endif
 
        // write record specific Data. 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter)
        { 
            // write out an int for attribute Id
            bamlBinaryWriter.Write(AttributeId);
        }
 
        #endregion Methods
 
        #region Properties 
        // Id of the property being set as the context
        internal short AttributeId 
        {
            get { return _attributeId; }
            set { _attributeId = value; }
        } 

        // Additional properties not stored in the baml stream 
        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.ContentProperty; } 
        }

        // True if there is a serializer associated with this type
        internal virtual bool HasSerializer 
        {
            get { return false; } 
        } 
        #endregion Properties
 
        #region Data
        short _attributeId = -1;
        #endregion Data
    } 

 
    // Debugging Linenumber record.  Linenumber from the XAML 
    // 
    // This code should always be transparent.  Meaning you should never add 
    // SecurityCritical to this section of the code.
    // 
    internal class BamlLineAndPositionRecord : BamlRecord
    { 

#region Methods 
 
#if !PBTCOMPILER
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader) 
        {
            LineNumber = (uint) bamlBinaryReader.ReadInt32();
            LinePosition = (uint) bamlBinaryReader.ReadInt32();
        } 
#endif
 
        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(LineNumber); 
            bamlBinaryWriter.Write(LinePosition);
        }

#endregion Methods 

#region Properties 
 
        internal override BamlRecordType RecordType
        { 
            get { return BamlRecordType.LineNumberAndPosition; }
        }

        // Id of the type of this object 
        internal uint LineNumber
        { 
            get { return _lineNumber; } 
            set { _lineNumber = value; }
        } 

        internal uint LinePosition
        {
            get { return _linePosition; } 
            set { _linePosition = value; }
        } 
 
        internal override Int32 RecordSize
        { 
            get { return 8; }
        }

        uint _lineNumber; 
        uint _linePosition;
 
#endregion Properties 

#if !PBTCOMPILER 
        public override string ToString()
        {
            return string.Format(CultureInfo.InvariantCulture,
                                 "{0} LineNum={1} Pos={2}", RecordType, LineNumber, LinePosition); 
        }
#endif 
    } 

 
    // Debugging Line Position record.  Line Position from the XAML
    // 
    // This code should always be transparent.  Meaning you should never add
    // SecurityCritical to this section of the code. 
    // 
    internal class BamlLinePositionRecord : BamlRecord 
    { 

#region Methods 

#if !PBTCOMPILER
        internal override void  LoadRecordData(BinaryReader bamlBinaryReader)
        { 
            LinePosition = (uint) bamlBinaryReader.ReadInt32();
        } 
#endif 

        internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) 
        {
            bamlBinaryWriter.Write(LinePosition);
        }
 
#endregion Methods
 
#region Properties 

        internal override BamlRecordType RecordType 
        {
            get { return BamlRecordType.LinePosition; }
        }
 
        internal uint LinePosition
        { 
            get { return _linePosition; } 
            set { _linePosition = value; }
        } 

        internal override Int32 RecordSize
        {
            get { return 4; } 
        }
 
        uint _linePosition; 

#endregion Properties 

#if !PBTCOMPILER
        public override string ToString()
        { 
            return string.Format(CultureInfo.InvariantCulture,
                                 "{0} LinePos={1}", RecordType, LinePosition); 
        } 
#endif
    } 


}

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