OptimizedTemplateContentHelper.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Markup / OptimizedTemplateContentHelper.cs / 1 / OptimizedTemplateContentHelper.cs

                            /****************************************************************************\ 
*
* File: OptimizedTemplateContentHelper.cs
*
* Purpose:  Main class to handle reading a Template Baml records from a stream 
*
* This is a BamlRecordReader that processes the baml records for shared 
* template values.  When it reaches the end of a shared value, the 
* OptimizedTemplateContent class adds the value to its shared values table.
* If we discover here a record that's not shareable, then the OptimizedTemplateContent 
* class unwinds what we've done.
*
* Copyright (C) 2005 by Microsoft Corporation.  All rights reserved.
* 
\***************************************************************************/
 
using System; 
using System.Xml;
using System.IO; 
using System.Windows;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Text; 
using System.Collections;
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Windows.Controls;
using System.Windows.Documents; 
using System.Windows.Media.Animation;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Threading; 
using System.Windows.Data;
 
using System.Globalization; 
using MS.Utility;
 
namespace System.Windows.Markup
{

    internal class OptimizedTemplateContentHelper : BamlRecordReader 
    {
 
#region Internals 

        /***************************************************************************\ 
        *
        * OptimizedTemplateContentHelper
        *
        * Create a new reader. 
        *
        \***************************************************************************/ 
 
        internal OptimizedTemplateContentHelper(ParserContext context)
        { 

            SetPreviousBamlRecordReader(context.BamlReader);

            BamlStream = context.BamlReader.BamlStream; 
            ParserContext = context;
 
            Reset(); 
        }
 
        /***************************************************************************\
        *
        * OptimizedTemplateContentHelper.Reset
        * 
        * Return reader to starting state, ready to load a sequence of baml records.
        * 
        \***************************************************************************/ 

        internal void Reset() 
        {
            _subtreeState = BamlSubtreeState.ContinueShareableSubtree;

            if (RootList == null) 
            {
                RootList = new ArrayList(1); 
            } 
            else
            { 
                RootList.Clear();
            }

            ContextStack.Clear(); 

            // Restore the ParserContext back to the primary record reader. 
            ParserContext.BamlReader = PreviousBamlRecordReader; 

        } 

        internal void ReadCustomProperty(BamlPropertyCustomRecord bamlPropertyCustomRecord)
        {
            if (bamlPropertyCustomRecord.SerializerTypeId == (short)KnownElements.DependencyPropertyConverter) 
            {
                GetCustomDependencyPropertyValue(bamlPropertyCustomRecord); 
            } 
            else
            { 
                string propName = null;
                Type propType = null;
                short attributeId = bamlPropertyCustomRecord.AttributeId;
                DependencyProperty dp = MapTable.GetDependencyProperty(attributeId); 

                if (dp == null) 
                { 
                    propType = MapTable.GetCLRPropertyTypeAndNameFromId(attributeId, out propName);
                } 
                else
                {
                    propType = dp.PropertyType;
                    propName = dp.Name; 
                }
 
                // Read the custom property value into the record. 
                GetCustomValue(bamlPropertyCustomRecord, propType, propName);
            } 
        }

        /***************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadSubtreeRecord
        * 
        * Read the current record and return an indication of whether we should 
        * continue building a shared tree, or whether some condition was encountered
        * that makes this tree unshareable. 
        *
        \***************************************************************************/

        internal BamlSubtreeState ReadSubtreeRecord(BamlRecord record) 
        {
            // Point the ParserContext to this record reader (this gets reset by the Reset 
            // method). 

            ParserContext.BamlReader = this; 

            // If we're not currently in a nested serializer, and this is an element start,
            // see if we need to go into one.
 
            if( _nestedSerializerStartRecord == null
                && 
                record.RecordType == BamlRecordType.ElementStart) 
            {
                // See if this has a custom serializer. 

                BamlElementStartRecord  bamlElementStartRecord = record as BamlElementStartRecord;
                if( MapTable.HasSerializerForTypeId(bamlElementStartRecord.TypeId) )
                { 
                    // This element has its own custom serializer.  Keep track of where it starts,
                    // so that when it ends, we can just pass the whole thing off. 
 
                    _nestedSerializerStartRecord = record;
 
                    Debug.Assert( _subtreeState == BamlSubtreeState.ContinueShareableSubtree );
                    Debug.Assert( _nestedRecordDepth == 0 );
                }
            } 

            // Are we in a custom serializer? 
 
            if( _nestedSerializerStartRecord != null )
            { 
                Debug.Assert( _subtreeState == BamlSubtreeState.ContinueShareableSubtree );

                // Yes, we're in a custom serializer.  Update the record depth
 
                if( record.RecordType == BamlRecordType.ElementStart )
                { 
                    int positiveTypeId = -((BamlElementStartRecord)record).TypeId; 
                    if (positiveTypeId == (int)KnownElements.StaticResourceExtension)
                    { 
                        _subtreeState = BamlSubtreeState.NotShareable;
                    }
                    else
                    { 
                        ++_nestedRecordDepth;
                    } 
                } 
                else if( record.RecordType == BamlRecordType.ElementEnd )
                { 
                    --_nestedRecordDepth;
                }
                else if( record.RecordType == BamlRecordType.StaticResourceId ||
                         record.RecordType == BamlRecordType.PropertyWithStaticResourceId ) 
                {
                    _subtreeState = BamlSubtreeState.NotShareable; 
                } 
                else if( record.RecordType == BamlRecordType.PropertyWithExtension )
                { 
                    int positiveTypeId = ((BamlPropertyWithExtensionRecord)record).ExtensionTypeId;
                    if (positiveTypeId == (int)KnownElements.StaticResourceExtension)
                    {
                        _subtreeState = BamlSubtreeState.NotShareable; 
                    }
                } 
                else if (record.RecordType == BamlRecordType.PropertyCustom) 
                {
                    // if this is a custom proeprty, the raw custom value must be read into 
                    // the record to "finish" fully reading teh custom record.
                    BamlPropertyCustomRecord bamlPropertyCustomRecord = record as BamlPropertyCustomRecord;
                    ReadCustomProperty(bamlPropertyCustomRecord);
                } 

                // When we have a StaticResource within an element with a custom serializer, 
                // the element is non-shareable. For example a nested Template with 
                // StaticResources in it.
 
                if( _subtreeState == BamlSubtreeState.NotShareable )
                {
                    // Reset.
                    _nestedSerializerStartRecord = null; 
                    _nestedRecordDepth = 0;
                } 
                else 
                {
                    // Did we reach the end record for the custom-serialized element? 

                    if( _nestedRecordDepth == 0 )
                    {
                        Debug.Assert( record.RecordType == BamlRecordType.ElementEnd ); 

                        // Yes, we're at the end, let it run now. 
 
                        PreParsedRecordsStart = _nestedSerializerStartRecord;
                        PreParsedCurrentRecord = _nestedSerializerStartRecord.Next; 

                        // If the first record has a debug extension following it
                        // process the debugging information before the record.
                        if (BamlRecordHelper.HasDebugExtensionRecord(ParserContext.IsDebugBamlStream, PreParsedRecordsStart)) 
                        {
                            ProcessDebugBamlRecord(PreParsedCurrentRecord); 
                            PreParsedCurrentRecord = PreParsedCurrentRecord.Next; 
                        }
 
                        base.ReadRecord( _nestedSerializerStartRecord );

                        // Reset.
                        _nestedSerializerStartRecord = null; 
                    }
                } 
            } 

            // Or if we're not in a custom serializer, just call base 
            else
            {
                // If the record has a debug extension following it
                // process the debugging information before the record. 
                if (BamlRecordHelper.HasDebugExtensionRecord(ParserContext.IsDebugBamlStream, record))
                { 
                    ProcessDebugBamlRecord(record.Next); 
                }
                base.ReadRecord(record); 
            }

            // Return the (possibly just updated) state, indicating if we're still
            // shareable, etc. 

            return _subtreeState; 
 
        }
 
#endregion Internals

#region Overrides
 
        /****************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadElementStartRecord 
        *
        * Read the start of an element.  This involves creating a new object, and 
        * storing it for later addition to the tree or setting as a property.  If
        * the element is a Visual or ContentElement, then the constructed tree
        * cannot be shared.
        * 
        \***************************************************************************/
 
        protected override bool ReadElementStartRecord( 
            BamlElementStartRecord bamlElementRecord)
        { 
            Type elementType = MapTable.GetTypeFromId(bamlElementRecord.TypeId);

            if( !OptimizedTemplateContent.IsShareableType(elementType) )
            { 
                _subtreeState = BamlSubtreeState.NotShareable;
                return false; 
            } 
            else
            { 
                return base.ReadElementStartRecord(bamlElementRecord);
            }
        }
 
        /***************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadStaticResourceIdRecord 
        *
        * StaticResourceExtensions within template content are nt shareable because 
        * they will need to be re-evaluated within the scope of the template
        * generated tree (cause we could have a ResourceDictionary on some element
        * in there).
        * 
        \***************************************************************************/
        protected override void ReadStaticResourceIdRecord( 
            BamlStaticResourceIdRecord bamlStaticResourceIdRecord) 
        {
            _subtreeState = BamlSubtreeState.NotShareable; 
        }

        /****************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadPropertyWithStaticResourceIdRecord
        * 
        * StaticResourceExtensions within template content are not shareable because 
        * they will need to be re-evaluated within the scope of the template
        * generated tree (cause we could have a ResourceDictionary on some element 
        * in there).
        *
        \***************************************************************************/
        protected override void ReadPropertyWithStaticResourceIdRecord( 
            BamlPropertyWithStaticResourceIdRecord bamlPropertyWithStaticResourceIdRecord)
        { 
            _subtreeState = BamlSubtreeState.NotShareable; 
        }
 
        /****************************************************************************\
        *
        * OptimizedTemplateContentHelper.ReadPropertyWithExtensionRecord
        * 
        * StaticResourceExtensions within template content are not shareable because
        * they will need to be re-evaluated within the scope of the template 
        * generated tree (cause we could have a ResourceDictionary on some element 
        * in there).
        * 
        \***************************************************************************/
        protected override void ReadPropertyWithExtensionRecord(
            BamlPropertyWithExtensionRecord bamlPropertyWithExtensionRecord)
        { 
            if (bamlPropertyWithExtensionRecord.ExtensionTypeId == (short)KnownElements.StaticResourceExtension)
            { 
                _subtreeState = BamlSubtreeState.NotShareable; 
            }
            else 
            {
                base.ReadPropertyWithExtensionRecord(bamlPropertyWithExtensionRecord);
            }
        } 

        /***************************************************************************\ 
        * 
        * OptimizedTemplateContentHelper.ReadConnectionId
        * 
        * Events cannot be in a shareable section, and this is indicated by
        * having a connection ID in the baml record sequence.
        *
        \***************************************************************************/ 

        protected override void ReadConnectionId( 
            BamlConnectionIdRecord bamlConnectionIdRecord) 
        {
            _subtreeState = BamlSubtreeState.NotShareable; 
        }

        /****************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadPropertyRecord
        * 
        * Read a string property.  If this is for x:Name, then the subtree is 
        * not shareable
        * 
        \***************************************************************************/

        protected override void ReadPropertyRecord(
            BamlPropertyRecord bamlPropertyRecord) 
        {
            if (MapTable.DoesAttributeMatch(bamlPropertyRecord.AttributeId, BamlAttributeUsage.RuntimeName)) 
            { 
                _subtreeState = BamlSubtreeState.NotShareable;
            } 
            else
            {
                base.ReadPropertyRecord(bamlPropertyRecord);
            } 
        }
 
        /***************************************************************************\ 
        *
        * OptimizedTemplateContentHelper.ReadTextRecord 
        *
        * Only allow whitespace text content, which is generally ignored by
        * elements.
        * 
        \***************************************************************************/
 
        protected override void ReadTextRecord(BamlTextRecord bamlTextRecord) 
        {
            if( (CurrentContext.ContextFlags & ReaderFlags.PropertyComplexClr) != 0 ) 
            {
                base.ReadTextRecord( bamlTextRecord );
            }
            else 
            {
                int i; 
                string s = bamlTextRecord.Value; 
                for (i = 0; i < s.Length; i++)
                { 
                    if (!Char.IsWhiteSpace(s[i]))
                    {
                        _subtreeState = BamlSubtreeState.NotShareable;
                        break; 
                    }
                } 
 
                if( i == s.Length )
                { 
                    base.ReadTextRecord( bamlTextRecord );
                }
            }
        } 

        /***************************************************************************\ 
        * 
        * OptimizedTemplateContentHelper.ReadDefAttributeRecord
        * 
        * A Def tag has been found.  If this is for x:Name, then the subtree is
        * not shareable
        *
        \***************************************************************************/ 

        protected override void ReadDefAttributeRecord( 
            BamlDefAttributeRecord bamlDefAttributeRecord) 
        {
            if (bamlDefAttributeRecord.NameId == BamlMapTable.NameStringId) 
            {
                _subtreeState = BamlSubtreeState.NotShareable;
            }
            else 
            {
                base.ReadDefAttributeRecord(bamlDefAttributeRecord); 
            } 
        }
 
        /***************************************************************************\
        *
        * OptimizedTemplateContentHelper.ReadPropertyComplexEndRecord
        * 
        * If we hit the end of a complex property, and there is nothing on the
        * context stack, then we've popped out of the subtree we were building, 
        * so signal this by setting the appropriate state. 
        *
        \***************************************************************************/ 

        protected override void ReadPropertyComplexEndRecord()
        {
            if (CurrentContext == null) 
            {
                _subtreeState = BamlSubtreeState.EndShareableSubtree; 
            } 
            else
            { 
                base.ReadPropertyComplexEndRecord();
            }
        }
 
        /****************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadPropertyIListEndRecord 
        *
        * If we hit the end of a complex property, and there is nothing on the 
        * context stack, then we've popped out of the subtree we were building,
        * so signal this by setting the appropriate state.
        *
        \***************************************************************************/ 

        protected override void ReadPropertyIListEndRecord() 
        { 
            if (CurrentContext == null)
            { 
                _subtreeState = BamlSubtreeState.EndShareableSubtree;
            }
            else
            { 
                base.ReadPropertyIListEndRecord();
            } 
        } 

        /***************************************************************************\ 
        *
        * OptimizedTemplateContentHelper.ReadPropertyIDictionarEndRecord
        *
        * If we hit the end of a complex property, and there is nothing on the 
        * context stack, then we've popped out of the subtree we were building,
        * so signal this by setting the appropriate state. 
        * 
        \***************************************************************************/
 
        protected override void ReadPropertyIDictionaryEndRecord()
        {
            if (CurrentContext == null)
            { 
                _subtreeState = BamlSubtreeState.EndShareableSubtree;
            } 
            else 
            {
                base.ReadPropertyIDictionaryEndRecord(); 
            }
        }

        /****************************************************************************\ 
        *
        * OptimizedTemplateContentHelper.ReadPropertyArrayEndRecord 
        * 
        * If we hit the end of a complex property, and there is nothing on the
        * context stack, then we've popped out of the subtree we were building, 
        * so signal this by setting the appropriate state.
        *
        \***************************************************************************/
 
        protected override void ReadPropertyArrayEndRecord()
        { 
            if (CurrentContext == null) 
            {
                _subtreeState = BamlSubtreeState.EndShareableSubtree; 
            }
            else
            {
                base.ReadPropertyArrayEndRecord(); 
            }
        } 
 
        // Since TemplateBinding can only be used in Templates this is overridden and
        // specifically handled here. 
        internal override object GetExtensionValue(
            IOptimizedMarkupExtension optimizedMarkupExtensionRecord,
            string                    propertyName)
        { 
            object valueObject = null;
            short extensionTypeId = optimizedMarkupExtensionRecord.ExtensionTypeId; 
 
            if (extensionTypeId == (short)KnownElements.TemplateBindingExtension)
            { 
                short memberId = optimizedMarkupExtensionRecord.ValueId;
                DependencyProperty dp = MapTable.GetDependencyPropertyValueFromId(memberId);
                if (dp != null)
                { 
                    valueObject = new TemplateBindingExtension(dp);
                } 
                else 
                {
                    ThrowException(SRID.ParserCannotConvertPropertyValue, 
                                   propertyName,
                                   typeof(TemplateBindingExtension).FullName);
                }
            } 
            else
            { 
                valueObject = base.GetExtensionValue(optimizedMarkupExtensionRecord, propertyName); 
            }
 
            return valueObject;
        }

#endregion Overrides 

#region Data 
 
        private BamlSubtreeState _subtreeState;
        private BamlRecord _nestedSerializerStartRecord; 
        private int _nestedRecordDepth;

#endregion Data
    } 

} 
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
/****************************************************************************\ 
*
* File: OptimizedTemplateContentHelper.cs
*
* Purpose:  Main class to handle reading a Template Baml records from a stream 
*
* This is a BamlRecordReader that processes the baml records for shared 
* template values.  When it reaches the end of a shared value, the 
* OptimizedTemplateContent class adds the value to its shared values table.
* If we discover here a record that's not shareable, then the OptimizedTemplateContent 
* class unwinds what we've done.
*
* Copyright (C) 2005 by Microsoft Corporation.  All rights reserved.
* 
\***************************************************************************/
 
using System; 
using System.Xml;
using System.IO; 
using System.Windows;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Text; 
using System.Collections;
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Windows.Controls;
using System.Windows.Documents; 
using System.Windows.Media.Animation;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Threading; 
using System.Windows.Data;
 
using System.Globalization; 
using MS.Utility;
 
namespace System.Windows.Markup
{

    internal class OptimizedTemplateContentHelper : BamlRecordReader 
    {
 
#region Internals 

        /***************************************************************************\ 
        *
        * OptimizedTemplateContentHelper
        *
        * Create a new reader. 
        *
        \***************************************************************************/ 
 
        internal OptimizedTemplateContentHelper(ParserContext context)
        { 

            SetPreviousBamlRecordReader(context.BamlReader);

            BamlStream = context.BamlReader.BamlStream; 
            ParserContext = context;
 
            Reset(); 
        }
 
        /***************************************************************************\
        *
        * OptimizedTemplateContentHelper.Reset
        * 
        * Return reader to starting state, ready to load a sequence of baml records.
        * 
        \***************************************************************************/ 

        internal void Reset() 
        {
            _subtreeState = BamlSubtreeState.ContinueShareableSubtree;

            if (RootList == null) 
            {
                RootList = new ArrayList(1); 
            } 
            else
            { 
                RootList.Clear();
            }

            ContextStack.Clear(); 

            // Restore the ParserContext back to the primary record reader. 
            ParserContext.BamlReader = PreviousBamlRecordReader; 

        } 

        internal void ReadCustomProperty(BamlPropertyCustomRecord bamlPropertyCustomRecord)
        {
            if (bamlPropertyCustomRecord.SerializerTypeId == (short)KnownElements.DependencyPropertyConverter) 
            {
                GetCustomDependencyPropertyValue(bamlPropertyCustomRecord); 
            } 
            else
            { 
                string propName = null;
                Type propType = null;
                short attributeId = bamlPropertyCustomRecord.AttributeId;
                DependencyProperty dp = MapTable.GetDependencyProperty(attributeId); 

                if (dp == null) 
                { 
                    propType = MapTable.GetCLRPropertyTypeAndNameFromId(attributeId, out propName);
                } 
                else
                {
                    propType = dp.PropertyType;
                    propName = dp.Name; 
                }
 
                // Read the custom property value into the record. 
                GetCustomValue(bamlPropertyCustomRecord, propType, propName);
            } 
        }

        /***************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadSubtreeRecord
        * 
        * Read the current record and return an indication of whether we should 
        * continue building a shared tree, or whether some condition was encountered
        * that makes this tree unshareable. 
        *
        \***************************************************************************/

        internal BamlSubtreeState ReadSubtreeRecord(BamlRecord record) 
        {
            // Point the ParserContext to this record reader (this gets reset by the Reset 
            // method). 

            ParserContext.BamlReader = this; 

            // If we're not currently in a nested serializer, and this is an element start,
            // see if we need to go into one.
 
            if( _nestedSerializerStartRecord == null
                && 
                record.RecordType == BamlRecordType.ElementStart) 
            {
                // See if this has a custom serializer. 

                BamlElementStartRecord  bamlElementStartRecord = record as BamlElementStartRecord;
                if( MapTable.HasSerializerForTypeId(bamlElementStartRecord.TypeId) )
                { 
                    // This element has its own custom serializer.  Keep track of where it starts,
                    // so that when it ends, we can just pass the whole thing off. 
 
                    _nestedSerializerStartRecord = record;
 
                    Debug.Assert( _subtreeState == BamlSubtreeState.ContinueShareableSubtree );
                    Debug.Assert( _nestedRecordDepth == 0 );
                }
            } 

            // Are we in a custom serializer? 
 
            if( _nestedSerializerStartRecord != null )
            { 
                Debug.Assert( _subtreeState == BamlSubtreeState.ContinueShareableSubtree );

                // Yes, we're in a custom serializer.  Update the record depth
 
                if( record.RecordType == BamlRecordType.ElementStart )
                { 
                    int positiveTypeId = -((BamlElementStartRecord)record).TypeId; 
                    if (positiveTypeId == (int)KnownElements.StaticResourceExtension)
                    { 
                        _subtreeState = BamlSubtreeState.NotShareable;
                    }
                    else
                    { 
                        ++_nestedRecordDepth;
                    } 
                } 
                else if( record.RecordType == BamlRecordType.ElementEnd )
                { 
                    --_nestedRecordDepth;
                }
                else if( record.RecordType == BamlRecordType.StaticResourceId ||
                         record.RecordType == BamlRecordType.PropertyWithStaticResourceId ) 
                {
                    _subtreeState = BamlSubtreeState.NotShareable; 
                } 
                else if( record.RecordType == BamlRecordType.PropertyWithExtension )
                { 
                    int positiveTypeId = ((BamlPropertyWithExtensionRecord)record).ExtensionTypeId;
                    if (positiveTypeId == (int)KnownElements.StaticResourceExtension)
                    {
                        _subtreeState = BamlSubtreeState.NotShareable; 
                    }
                } 
                else if (record.RecordType == BamlRecordType.PropertyCustom) 
                {
                    // if this is a custom proeprty, the raw custom value must be read into 
                    // the record to "finish" fully reading teh custom record.
                    BamlPropertyCustomRecord bamlPropertyCustomRecord = record as BamlPropertyCustomRecord;
                    ReadCustomProperty(bamlPropertyCustomRecord);
                } 

                // When we have a StaticResource within an element with a custom serializer, 
                // the element is non-shareable. For example a nested Template with 
                // StaticResources in it.
 
                if( _subtreeState == BamlSubtreeState.NotShareable )
                {
                    // Reset.
                    _nestedSerializerStartRecord = null; 
                    _nestedRecordDepth = 0;
                } 
                else 
                {
                    // Did we reach the end record for the custom-serialized element? 

                    if( _nestedRecordDepth == 0 )
                    {
                        Debug.Assert( record.RecordType == BamlRecordType.ElementEnd ); 

                        // Yes, we're at the end, let it run now. 
 
                        PreParsedRecordsStart = _nestedSerializerStartRecord;
                        PreParsedCurrentRecord = _nestedSerializerStartRecord.Next; 

                        // If the first record has a debug extension following it
                        // process the debugging information before the record.
                        if (BamlRecordHelper.HasDebugExtensionRecord(ParserContext.IsDebugBamlStream, PreParsedRecordsStart)) 
                        {
                            ProcessDebugBamlRecord(PreParsedCurrentRecord); 
                            PreParsedCurrentRecord = PreParsedCurrentRecord.Next; 
                        }
 
                        base.ReadRecord( _nestedSerializerStartRecord );

                        // Reset.
                        _nestedSerializerStartRecord = null; 
                    }
                } 
            } 

            // Or if we're not in a custom serializer, just call base 
            else
            {
                // If the record has a debug extension following it
                // process the debugging information before the record. 
                if (BamlRecordHelper.HasDebugExtensionRecord(ParserContext.IsDebugBamlStream, record))
                { 
                    ProcessDebugBamlRecord(record.Next); 
                }
                base.ReadRecord(record); 
            }

            // Return the (possibly just updated) state, indicating if we're still
            // shareable, etc. 

            return _subtreeState; 
 
        }
 
#endregion Internals

#region Overrides
 
        /****************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadElementStartRecord 
        *
        * Read the start of an element.  This involves creating a new object, and 
        * storing it for later addition to the tree or setting as a property.  If
        * the element is a Visual or ContentElement, then the constructed tree
        * cannot be shared.
        * 
        \***************************************************************************/
 
        protected override bool ReadElementStartRecord( 
            BamlElementStartRecord bamlElementRecord)
        { 
            Type elementType = MapTable.GetTypeFromId(bamlElementRecord.TypeId);

            if( !OptimizedTemplateContent.IsShareableType(elementType) )
            { 
                _subtreeState = BamlSubtreeState.NotShareable;
                return false; 
            } 
            else
            { 
                return base.ReadElementStartRecord(bamlElementRecord);
            }
        }
 
        /***************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadStaticResourceIdRecord 
        *
        * StaticResourceExtensions within template content are nt shareable because 
        * they will need to be re-evaluated within the scope of the template
        * generated tree (cause we could have a ResourceDictionary on some element
        * in there).
        * 
        \***************************************************************************/
        protected override void ReadStaticResourceIdRecord( 
            BamlStaticResourceIdRecord bamlStaticResourceIdRecord) 
        {
            _subtreeState = BamlSubtreeState.NotShareable; 
        }

        /****************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadPropertyWithStaticResourceIdRecord
        * 
        * StaticResourceExtensions within template content are not shareable because 
        * they will need to be re-evaluated within the scope of the template
        * generated tree (cause we could have a ResourceDictionary on some element 
        * in there).
        *
        \***************************************************************************/
        protected override void ReadPropertyWithStaticResourceIdRecord( 
            BamlPropertyWithStaticResourceIdRecord bamlPropertyWithStaticResourceIdRecord)
        { 
            _subtreeState = BamlSubtreeState.NotShareable; 
        }
 
        /****************************************************************************\
        *
        * OptimizedTemplateContentHelper.ReadPropertyWithExtensionRecord
        * 
        * StaticResourceExtensions within template content are not shareable because
        * they will need to be re-evaluated within the scope of the template 
        * generated tree (cause we could have a ResourceDictionary on some element 
        * in there).
        * 
        \***************************************************************************/
        protected override void ReadPropertyWithExtensionRecord(
            BamlPropertyWithExtensionRecord bamlPropertyWithExtensionRecord)
        { 
            if (bamlPropertyWithExtensionRecord.ExtensionTypeId == (short)KnownElements.StaticResourceExtension)
            { 
                _subtreeState = BamlSubtreeState.NotShareable; 
            }
            else 
            {
                base.ReadPropertyWithExtensionRecord(bamlPropertyWithExtensionRecord);
            }
        } 

        /***************************************************************************\ 
        * 
        * OptimizedTemplateContentHelper.ReadConnectionId
        * 
        * Events cannot be in a shareable section, and this is indicated by
        * having a connection ID in the baml record sequence.
        *
        \***************************************************************************/ 

        protected override void ReadConnectionId( 
            BamlConnectionIdRecord bamlConnectionIdRecord) 
        {
            _subtreeState = BamlSubtreeState.NotShareable; 
        }

        /****************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadPropertyRecord
        * 
        * Read a string property.  If this is for x:Name, then the subtree is 
        * not shareable
        * 
        \***************************************************************************/

        protected override void ReadPropertyRecord(
            BamlPropertyRecord bamlPropertyRecord) 
        {
            if (MapTable.DoesAttributeMatch(bamlPropertyRecord.AttributeId, BamlAttributeUsage.RuntimeName)) 
            { 
                _subtreeState = BamlSubtreeState.NotShareable;
            } 
            else
            {
                base.ReadPropertyRecord(bamlPropertyRecord);
            } 
        }
 
        /***************************************************************************\ 
        *
        * OptimizedTemplateContentHelper.ReadTextRecord 
        *
        * Only allow whitespace text content, which is generally ignored by
        * elements.
        * 
        \***************************************************************************/
 
        protected override void ReadTextRecord(BamlTextRecord bamlTextRecord) 
        {
            if( (CurrentContext.ContextFlags & ReaderFlags.PropertyComplexClr) != 0 ) 
            {
                base.ReadTextRecord( bamlTextRecord );
            }
            else 
            {
                int i; 
                string s = bamlTextRecord.Value; 
                for (i = 0; i < s.Length; i++)
                { 
                    if (!Char.IsWhiteSpace(s[i]))
                    {
                        _subtreeState = BamlSubtreeState.NotShareable;
                        break; 
                    }
                } 
 
                if( i == s.Length )
                { 
                    base.ReadTextRecord( bamlTextRecord );
                }
            }
        } 

        /***************************************************************************\ 
        * 
        * OptimizedTemplateContentHelper.ReadDefAttributeRecord
        * 
        * A Def tag has been found.  If this is for x:Name, then the subtree is
        * not shareable
        *
        \***************************************************************************/ 

        protected override void ReadDefAttributeRecord( 
            BamlDefAttributeRecord bamlDefAttributeRecord) 
        {
            if (bamlDefAttributeRecord.NameId == BamlMapTable.NameStringId) 
            {
                _subtreeState = BamlSubtreeState.NotShareable;
            }
            else 
            {
                base.ReadDefAttributeRecord(bamlDefAttributeRecord); 
            } 
        }
 
        /***************************************************************************\
        *
        * OptimizedTemplateContentHelper.ReadPropertyComplexEndRecord
        * 
        * If we hit the end of a complex property, and there is nothing on the
        * context stack, then we've popped out of the subtree we were building, 
        * so signal this by setting the appropriate state. 
        *
        \***************************************************************************/ 

        protected override void ReadPropertyComplexEndRecord()
        {
            if (CurrentContext == null) 
            {
                _subtreeState = BamlSubtreeState.EndShareableSubtree; 
            } 
            else
            { 
                base.ReadPropertyComplexEndRecord();
            }
        }
 
        /****************************************************************************\
        * 
        * OptimizedTemplateContentHelper.ReadPropertyIListEndRecord 
        *
        * If we hit the end of a complex property, and there is nothing on the 
        * context stack, then we've popped out of the subtree we were building,
        * so signal this by setting the appropriate state.
        *
        \***************************************************************************/ 

        protected override void ReadPropertyIListEndRecord() 
        { 
            if (CurrentContext == null)
            { 
                _subtreeState = BamlSubtreeState.EndShareableSubtree;
            }
            else
            { 
                base.ReadPropertyIListEndRecord();
            } 
        } 

        /***************************************************************************\ 
        *
        * OptimizedTemplateContentHelper.ReadPropertyIDictionarEndRecord
        *
        * If we hit the end of a complex property, and there is nothing on the 
        * context stack, then we've popped out of the subtree we were building,
        * so signal this by setting the appropriate state. 
        * 
        \***************************************************************************/
 
        protected override void ReadPropertyIDictionaryEndRecord()
        {
            if (CurrentContext == null)
            { 
                _subtreeState = BamlSubtreeState.EndShareableSubtree;
            } 
            else 
            {
                base.ReadPropertyIDictionaryEndRecord(); 
            }
        }

        /****************************************************************************\ 
        *
        * OptimizedTemplateContentHelper.ReadPropertyArrayEndRecord 
        * 
        * If we hit the end of a complex property, and there is nothing on the
        * context stack, then we've popped out of the subtree we were building, 
        * so signal this by setting the appropriate state.
        *
        \***************************************************************************/
 
        protected override void ReadPropertyArrayEndRecord()
        { 
            if (CurrentContext == null) 
            {
                _subtreeState = BamlSubtreeState.EndShareableSubtree; 
            }
            else
            {
                base.ReadPropertyArrayEndRecord(); 
            }
        } 
 
        // Since TemplateBinding can only be used in Templates this is overridden and
        // specifically handled here. 
        internal override object GetExtensionValue(
            IOptimizedMarkupExtension optimizedMarkupExtensionRecord,
            string                    propertyName)
        { 
            object valueObject = null;
            short extensionTypeId = optimizedMarkupExtensionRecord.ExtensionTypeId; 
 
            if (extensionTypeId == (short)KnownElements.TemplateBindingExtension)
            { 
                short memberId = optimizedMarkupExtensionRecord.ValueId;
                DependencyProperty dp = MapTable.GetDependencyPropertyValueFromId(memberId);
                if (dp != null)
                { 
                    valueObject = new TemplateBindingExtension(dp);
                } 
                else 
                {
                    ThrowException(SRID.ParserCannotConvertPropertyValue, 
                                   propertyName,
                                   typeof(TemplateBindingExtension).FullName);
                }
            } 
            else
            { 
                valueObject = base.GetExtensionValue(optimizedMarkupExtensionRecord, propertyName); 
            }
 
            return valueObject;
        }

#endregion Overrides 

#region Data 
 
        private BamlSubtreeState _subtreeState;
        private BamlRecord _nestedSerializerStartRecord; 
        private int _nestedRecordDepth;

#endregion Data
    } 

} 
 

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