DataStreams.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / MS / Internal / DataStreams.cs / 1 / DataStreams.cs

                            //---------------------------------------------------------------------------- 
//
// File: DataStreams.cs
//
// Description: 
// Holds the data for Avalon BindProducts in the journal
// 
// 
// History:
//  7/30/2001:  t-ypchen        Created 
//  5/20/2003:  kusumav         Ported from to WCP_Dev
// 11/14/2005:  ChangoV         Refactoring as part of the "Island Frame" implementation;
//                              introduced the internal IJournalState interface.
// 
// Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
// 
//--------------------------------------------------------------------------- 

using System; 
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO; 
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary; 
using System.Security; 
using System.Security.Permissions;
using MS.Internal.AppModel; 
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives; 

namespace MS.Internal.AppModel 
{ 
    #region SubStream struct
    [Serializable] 
    internal struct SubStream
    {
        internal SubStream(string propertyName, byte[] dataBytes)
        { 
            _propertyName = propertyName;
            _data = dataBytes; 
        } 

        internal string _propertyName; 
        internal byte[] _data;
    }
    #endregion SubStream struct
 
    #region DataStreams class
    [Serializable] 
    internal class DataStreams 
    {
        ///  
        /// Critical - as the constructor initializes the Critical member _subStreams.
        /// Safe - as the initialization is to a safe value.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal DataStreams()
        { 
            // Dummy constructor to keep FxCop Critical rules happy. 
        }
 
        /// 
        /// Critical - as this refers to Critical member _subStreams.
        /// Safe - as this doesn't expose the data
        ///  
        internal bool HasAnyData
        { 
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                return _subStreams != null && _subStreams.Count > 0
                    || _customJournaledObjects != null && _customJournaledObjects.Count > 0;
            }
        } 

        ///  
        /// Critical - as this refers to Critical member _subStreams. 
        /// Safe - as this doesn't expose the data.  Returning if a stream exists
        ///        is not Critical information, the content of the stream is. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private bool HasSubStreams(object key)
        { 
            return _subStreams != null && _subStreams.Contains(key);
        } 
 
        /// 
        /// Critical - as this returns Critical data in _subStreams. 
        /// 
        [SecurityCritical]
        private ArrayList GetSubStreams(object key)
        { 
            ArrayList subStreams = (ArrayList) _subStreams[key];
            if (subStreams == null) 
            { 
                subStreams = new ArrayList(3);
                _subStreams[key] = subStreams; 
            }

            return subStreams;
        } 

        private delegate void NodeOperation(object node); 
 
        /// 
        /// Build an ArrayList of SubStreams where each SubStream represents one of the 
        /// node's journalable DPs.
        /// 
        /// 
        /// The ArrayList of SubStreams. May be null. 
        /// 
        /// Critical - as this calls Formatter.Serialize under an elevation and 
        ///            returns the value so obtained. 
        /// 
        [SecurityCritical] 
        private ArrayList SaveSubStreams(UIElement element)
        {
            ArrayList subStreams = null;
 
#pragma warning disable 618
            if ((element != null) && (element.PersistId != 0)) 
#pragma warning restore 618 
            {
                LocalValueEnumerator dpEnumerator = element.GetLocalValueEnumerator(); 

                while (dpEnumerator.MoveNext())
                {
                    LocalValueEntry localValueEntry = (LocalValueEntry)dpEnumerator.Current; 
                    FrameworkPropertyMetadata metadata = localValueEntry.Property.GetMetadata(element.DependencyObjectType) as FrameworkPropertyMetadata;
 
                    if (metadata == null) 
                    {
                        continue; 
                    }

                    // To be saved, a DP should have the correct metadata and NOT be an expression or data bound.
                    // Since Bind inherits from Expression, the test for Expression will suffice. 
                    // NOTE: we do not journal expression. So we should let parser restore it in BamlRecordReader.SetDependencyValue.
                    // Please see Windows OS bug # 1852349 for details. 
                    if (metadata.Journal && (!(localValueEntry.Value is Expression))) 
                    {
                        // These properties should not be journaled. 
                        //

                        if (object.ReferenceEquals(localValueEntry.Property, Frame.SourceProperty))
                            continue; 

                        if (subStreams == null) 
                        { 
                            subStreams = new ArrayList(3);
                        } 

                        object currentValue = element.GetValue(localValueEntry.Property);
                        byte[] bytes = null;
 
                        if ((currentValue != null) && !(currentValue is Uri))
                        { 
                            // Convert the value of the DP into a byte array 
                            MemoryStream byteStream = new MemoryStream();
                            new SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert(); 
                            try
                            {
                                this.Formatter.Serialize(byteStream, currentValue);
                            } 
                            finally
                            { 
                                SecurityPermission.RevertAssert(); 
                            }
 
                            bytes = byteStream.ToArray();
                            // Dispose the stream
                            ((IDisposable)byteStream).Dispose( );
                        } 

                        // Save the byte array by the property name 
                        subStreams.Add(new SubStream(localValueEntry.Property.Name, bytes)); 
                    }
                } 
            }

            return subStreams;
        } 

        ///  
        /// Critical - as this invokes Critical function SaveSubStreams and sets data 
        ///            in Critical member _subStreams.
        /// Safe - as this doesn't return the Critical data, so any private members that 
        ///        are saved from Serializing the object are protected.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void SaveState(object node) 
        {
            UIElement element = node as UIElement; 
            if (element == null) 
            {
                return; 
            }

            // Due to bug 1282529, PersistId can be null. Only XAML/BAML-loaded elements have it.
            // Besides for PageFunctions journaled by type, the PersistId check below is needed 
            // because elements might have been added to the tree after loading from XAML/BAML.
#pragma warning disable 618 
            int persistId = element.PersistId; 
#pragma warning restore 618
 
            if (persistId != 0)
            {
                ArrayList subStreams = this.SaveSubStreams(element);
                if (subStreams != null) 
                {
                    // 
                    // If one element in the tree is replaced with a new element which is created 
                    // from a xaml/baml stream programatically, this new element and all its descendent nodes
                    // would have another set of PersistId starting from 1, it would end up with two or more 
                    // elements in the same page share the same PersistId.  We cannot guarantee to restore
                    // journaldata for the newly added elements when doing the journaling navigation.
                    //
                    // So to do some level protection to avoid application crash, the code doesn't update the 
                    // journaldata for that element id if the data was set already.
                    // 
                    // 

 

                    if (!_subStreams.Contains(persistId))
                    {
                        _subStreams[persistId] = subStreams; 
                    }
                } 
 
                IJournalState customJournalingObject = node as IJournalState;
                if (customJournalingObject != null) 
                {
                    object customState = customJournalingObject.GetJournalState(JournalReason.NewContentNavigation);
                    if (customState != null)
                    { 
                        if (_customJournaledObjects == null)
                        { 
                            _customJournaledObjects = new HybridDictionary(2); 
                        }
 
                        //
                        // Again, We cannot guarantee the PeristId of all elements in the same page are unique.
                        // Some IJouralState aware node such as Frame, FlowDocumentPageViewer could be added
                        // programatically after the page is created from baml stream,  the new added node could also 
                        // be created from baml/xaml stream by Parser.
                        // 
                        if (!_customJournaledObjects.Contains(persistId)) 
                        {
                            _customJournaledObjects[persistId] = customState; 
                        }
                    }
                }
            } 
        }
 
        internal void PrepareForSerialization() 
        {
            if (_customJournaledObjects != null) 
            {
                foreach (DictionaryEntry entry in _customJournaledObjects)
                {
                    CustomJournalStateInternal cjs = (CustomJournalStateInternal)entry.Value; 
                    cjs.PrepareForSerialization();
                } 
            } 

            // Everything in _subStreams is already binary-serialized. 
        }

        /// 
        /// Critical - as this invokes Deserialize under an elevation on a random stream passed in. 
        /// 
        [SecurityCritical] 
        private void LoadSubStreams(UIElement element, ArrayList subStreams) 
        {
            for (int subStreamIndex = 0; subStreamIndex < subStreams.Count; ++subStreamIndex) 
            {
                SubStream subStream = (SubStream)subStreams[subStreamIndex];

                // Restore the value of an individual DP 
                DependencyProperty dp = DependencyProperty.FromName(subStream._propertyName, element.GetType());
                // If the dp cannot be found it may mean that we navigated back to a loose file that has been changed. 
                if (dp != null) 
                {
                    object newValue = null; 
                    if (subStream._data != null)
                    {
                        new SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert(); // BlessedAssert
                        try 
                        {
                            newValue = this.Formatter.Deserialize(new MemoryStream(subStream._data)); 
                        } 
                        finally
                        { 
                            SecurityPermission.RevertAssert();
                        }
                    }
                    element.SetValue(dp, newValue); 
                }
            } 
        } 

        ///  
        /// Critical - as this calls Critical functions GetSubStreams and LoadSubStreams.
        /// Safe - this does not return data obtained from GetSubStreams.  The call to
        ///        LoadSubStreams won't cause de-serialization of random data.  It'd only
        ///        cause deserializaton of data returned by GetSubStreams which returns an 
        ///        object from _subStreams array which is Critical and thus is tracked.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void LoadState(object node)
        { 
            UIElement element = node as UIElement;
            if (element == null)
            {
                return; 
            }
 
#pragma warning disable 618 
            int persistId = element.PersistId;
#pragma warning restore 618 

            // Due to bug 1282529, PersistId can be null. Only XAML/BAML-loaded elements have it.
            if (persistId != 0)
            { 
                if (this.HasSubStreams(persistId))
                { 
                    // Get the properties to restore 
                    ArrayList properties = this.GetSubStreams(persistId);
                    LoadSubStreams(element, properties); 
                }

                if (_customJournaledObjects != null && _customJournaledObjects.Contains(persistId))
                { 
                    CustomJournalStateInternal state =
                        (CustomJournalStateInternal)_customJournaledObjects[persistId]; 
                    Debug.Assert(state != null); 
                    IJournalState customJournalingObject = node as IJournalState;
 
                    //
                    // For below two scenarios, JournalData cannot be restored successfully. For now, we just
                    // simply ignore it and don't throw exception.
                    // 
                    //  A. After the tree was created from xaml/baml stream,  some elements might be replaced
                    //     programatically with new elements which could be created from other xaml/baml by Parser. 
                    // 
                    //  B. If the loose xaml file has been changed since the journal data was created
                    // 
                    //

                    if (customJournalingObject != null)
                    { 
                        customJournalingObject.RestoreJournalState(state);
                    } 
                } 
            }
        } 

        /// 
        /// Walk the logical tree, and perform an operation on all nodes and children of nodes.
        /// This is slightly more complex than it might otherwise be because it makes no assumptions 
        /// that the Logical Tree is strongly typed. It is the responsibility of the operation to make sure
        /// that it can handle the node it receives. 
        ///  
        /// 
        ///  
        private void WalkLogicalTree(object node, NodeOperation operation)
        {
            if (node != null)
            { 
                operation(node);
            } 
 
            DependencyObject treeNode = node as DependencyObject;
            if (treeNode == null) 
            {
                return;
            }
 
            IEnumerator e = LogicalTreeHelper.GetChildren(treeNode).GetEnumerator();
            if (e == null) 
            { 
                return;
            } 

            while (e.MoveNext())
            {
                WalkLogicalTree(e.Current, operation); 
            }
        } 
 
        /// 
        /// Critical - as this modifies Critical data member _subStreams. 
        /// Safe - as this just initializes it to a safe value.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void Save(Object root) 
        {
            if (_subStreams == null) 
            { 
                _subStreams = new HybridDictionary(3);
            } 
            else
            {
                _subStreams.Clear();
            } 
            WalkLogicalTree(root, new NodeOperation(this.SaveState));
        } 
 
        internal void Load(Object root)
        { 
            if (this.HasAnyData)
            {
                WalkLogicalTree(root, new NodeOperation(this.LoadState));
            } 
        }
 
        ///  
        /// Critical - as this refers to Critical member _subStreams.
        /// Safe - as this doesn't expose the data 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void Clear()
        { 
            _subStreams = null;
            _customJournaledObjects = null; 
        } 

        #region Private and internal fields and properties 
        private BinaryFormatter Formatter
        {
            get
            { 
                if (_formatter == null)
                { 
                    _formatter = new BinaryFormatter(); 
                }
 
                return _formatter;
            }
        }
 
        [ThreadStatic]
        static private BinaryFormatter _formatter; 
 
        /// 
        /// Critical - This data is critical for two reasons.  One is that this holds 
        ///            data obtained by invoking Serialization under elevation.  The
        ///            other is that we call DeSerialization on this data under elevation.
        /// 
        [SecurityCritical] 
        private HybridDictionary _subStreams = new HybridDictionary(3);
 
        ///  
        /// PersistId->CustomJournalStateInternal map
        /// . 
        /// 
        private HybridDictionary _customJournaledObjects;

        #endregion Private and internal fields and properties 
    }
    #endregion DataStreams class 
 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// File: DataStreams.cs
//
// Description: 
// Holds the data for Avalon BindProducts in the journal
// 
// 
// History:
//  7/30/2001:  t-ypchen        Created 
//  5/20/2003:  kusumav         Ported from to WCP_Dev
// 11/14/2005:  ChangoV         Refactoring as part of the "Island Frame" implementation;
//                              introduced the internal IJournalState interface.
// 
// Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
// 
//--------------------------------------------------------------------------- 

using System; 
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO; 
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary; 
using System.Security; 
using System.Security.Permissions;
using MS.Internal.AppModel; 
using System.Windows;
using System.Windows.Navigation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives; 

namespace MS.Internal.AppModel 
{ 
    #region SubStream struct
    [Serializable] 
    internal struct SubStream
    {
        internal SubStream(string propertyName, byte[] dataBytes)
        { 
            _propertyName = propertyName;
            _data = dataBytes; 
        } 

        internal string _propertyName; 
        internal byte[] _data;
    }
    #endregion SubStream struct
 
    #region DataStreams class
    [Serializable] 
    internal class DataStreams 
    {
        ///  
        /// Critical - as the constructor initializes the Critical member _subStreams.
        /// Safe - as the initialization is to a safe value.
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        internal DataStreams()
        { 
            // Dummy constructor to keep FxCop Critical rules happy. 
        }
 
        /// 
        /// Critical - as this refers to Critical member _subStreams.
        /// Safe - as this doesn't expose the data
        ///  
        internal bool HasAnyData
        { 
            [SecurityCritical, SecurityTreatAsSafe] 
            get
            { 
                return _subStreams != null && _subStreams.Count > 0
                    || _customJournaledObjects != null && _customJournaledObjects.Count > 0;
            }
        } 

        ///  
        /// Critical - as this refers to Critical member _subStreams. 
        /// Safe - as this doesn't expose the data.  Returning if a stream exists
        ///        is not Critical information, the content of the stream is. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private bool HasSubStreams(object key)
        { 
            return _subStreams != null && _subStreams.Contains(key);
        } 
 
        /// 
        /// Critical - as this returns Critical data in _subStreams. 
        /// 
        [SecurityCritical]
        private ArrayList GetSubStreams(object key)
        { 
            ArrayList subStreams = (ArrayList) _subStreams[key];
            if (subStreams == null) 
            { 
                subStreams = new ArrayList(3);
                _subStreams[key] = subStreams; 
            }

            return subStreams;
        } 

        private delegate void NodeOperation(object node); 
 
        /// 
        /// Build an ArrayList of SubStreams where each SubStream represents one of the 
        /// node's journalable DPs.
        /// 
        /// 
        /// The ArrayList of SubStreams. May be null. 
        /// 
        /// Critical - as this calls Formatter.Serialize under an elevation and 
        ///            returns the value so obtained. 
        /// 
        [SecurityCritical] 
        private ArrayList SaveSubStreams(UIElement element)
        {
            ArrayList subStreams = null;
 
#pragma warning disable 618
            if ((element != null) && (element.PersistId != 0)) 
#pragma warning restore 618 
            {
                LocalValueEnumerator dpEnumerator = element.GetLocalValueEnumerator(); 

                while (dpEnumerator.MoveNext())
                {
                    LocalValueEntry localValueEntry = (LocalValueEntry)dpEnumerator.Current; 
                    FrameworkPropertyMetadata metadata = localValueEntry.Property.GetMetadata(element.DependencyObjectType) as FrameworkPropertyMetadata;
 
                    if (metadata == null) 
                    {
                        continue; 
                    }

                    // To be saved, a DP should have the correct metadata and NOT be an expression or data bound.
                    // Since Bind inherits from Expression, the test for Expression will suffice. 
                    // NOTE: we do not journal expression. So we should let parser restore it in BamlRecordReader.SetDependencyValue.
                    // Please see Windows OS bug # 1852349 for details. 
                    if (metadata.Journal && (!(localValueEntry.Value is Expression))) 
                    {
                        // These properties should not be journaled. 
                        //

                        if (object.ReferenceEquals(localValueEntry.Property, Frame.SourceProperty))
                            continue; 

                        if (subStreams == null) 
                        { 
                            subStreams = new ArrayList(3);
                        } 

                        object currentValue = element.GetValue(localValueEntry.Property);
                        byte[] bytes = null;
 
                        if ((currentValue != null) && !(currentValue is Uri))
                        { 
                            // Convert the value of the DP into a byte array 
                            MemoryStream byteStream = new MemoryStream();
                            new SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert(); 
                            try
                            {
                                this.Formatter.Serialize(byteStream, currentValue);
                            } 
                            finally
                            { 
                                SecurityPermission.RevertAssert(); 
                            }
 
                            bytes = byteStream.ToArray();
                            // Dispose the stream
                            ((IDisposable)byteStream).Dispose( );
                        } 

                        // Save the byte array by the property name 
                        subStreams.Add(new SubStream(localValueEntry.Property.Name, bytes)); 
                    }
                } 
            }

            return subStreams;
        } 

        ///  
        /// Critical - as this invokes Critical function SaveSubStreams and sets data 
        ///            in Critical member _subStreams.
        /// Safe - as this doesn't return the Critical data, so any private members that 
        ///        are saved from Serializing the object are protected.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        private void SaveState(object node) 
        {
            UIElement element = node as UIElement; 
            if (element == null) 
            {
                return; 
            }

            // Due to bug 1282529, PersistId can be null. Only XAML/BAML-loaded elements have it.
            // Besides for PageFunctions journaled by type, the PersistId check below is needed 
            // because elements might have been added to the tree after loading from XAML/BAML.
#pragma warning disable 618 
            int persistId = element.PersistId; 
#pragma warning restore 618
 
            if (persistId != 0)
            {
                ArrayList subStreams = this.SaveSubStreams(element);
                if (subStreams != null) 
                {
                    // 
                    // If one element in the tree is replaced with a new element which is created 
                    // from a xaml/baml stream programatically, this new element and all its descendent nodes
                    // would have another set of PersistId starting from 1, it would end up with two or more 
                    // elements in the same page share the same PersistId.  We cannot guarantee to restore
                    // journaldata for the newly added elements when doing the journaling navigation.
                    //
                    // So to do some level protection to avoid application crash, the code doesn't update the 
                    // journaldata for that element id if the data was set already.
                    // 
                    // 

 

                    if (!_subStreams.Contains(persistId))
                    {
                        _subStreams[persistId] = subStreams; 
                    }
                } 
 
                IJournalState customJournalingObject = node as IJournalState;
                if (customJournalingObject != null) 
                {
                    object customState = customJournalingObject.GetJournalState(JournalReason.NewContentNavigation);
                    if (customState != null)
                    { 
                        if (_customJournaledObjects == null)
                        { 
                            _customJournaledObjects = new HybridDictionary(2); 
                        }
 
                        //
                        // Again, We cannot guarantee the PeristId of all elements in the same page are unique.
                        // Some IJouralState aware node such as Frame, FlowDocumentPageViewer could be added
                        // programatically after the page is created from baml stream,  the new added node could also 
                        // be created from baml/xaml stream by Parser.
                        // 
                        if (!_customJournaledObjects.Contains(persistId)) 
                        {
                            _customJournaledObjects[persistId] = customState; 
                        }
                    }
                }
            } 
        }
 
        internal void PrepareForSerialization() 
        {
            if (_customJournaledObjects != null) 
            {
                foreach (DictionaryEntry entry in _customJournaledObjects)
                {
                    CustomJournalStateInternal cjs = (CustomJournalStateInternal)entry.Value; 
                    cjs.PrepareForSerialization();
                } 
            } 

            // Everything in _subStreams is already binary-serialized. 
        }

        /// 
        /// Critical - as this invokes Deserialize under an elevation on a random stream passed in. 
        /// 
        [SecurityCritical] 
        private void LoadSubStreams(UIElement element, ArrayList subStreams) 
        {
            for (int subStreamIndex = 0; subStreamIndex < subStreams.Count; ++subStreamIndex) 
            {
                SubStream subStream = (SubStream)subStreams[subStreamIndex];

                // Restore the value of an individual DP 
                DependencyProperty dp = DependencyProperty.FromName(subStream._propertyName, element.GetType());
                // If the dp cannot be found it may mean that we navigated back to a loose file that has been changed. 
                if (dp != null) 
                {
                    object newValue = null; 
                    if (subStream._data != null)
                    {
                        new SecurityPermission(SecurityPermissionFlag.SerializationFormatter).Assert(); // BlessedAssert
                        try 
                        {
                            newValue = this.Formatter.Deserialize(new MemoryStream(subStream._data)); 
                        } 
                        finally
                        { 
                            SecurityPermission.RevertAssert();
                        }
                    }
                    element.SetValue(dp, newValue); 
                }
            } 
        } 

        ///  
        /// Critical - as this calls Critical functions GetSubStreams and LoadSubStreams.
        /// Safe - this does not return data obtained from GetSubStreams.  The call to
        ///        LoadSubStreams won't cause de-serialization of random data.  It'd only
        ///        cause deserializaton of data returned by GetSubStreams which returns an 
        ///        object from _subStreams array which is Critical and thus is tracked.
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private void LoadState(object node)
        { 
            UIElement element = node as UIElement;
            if (element == null)
            {
                return; 
            }
 
#pragma warning disable 618 
            int persistId = element.PersistId;
#pragma warning restore 618 

            // Due to bug 1282529, PersistId can be null. Only XAML/BAML-loaded elements have it.
            if (persistId != 0)
            { 
                if (this.HasSubStreams(persistId))
                { 
                    // Get the properties to restore 
                    ArrayList properties = this.GetSubStreams(persistId);
                    LoadSubStreams(element, properties); 
                }

                if (_customJournaledObjects != null && _customJournaledObjects.Contains(persistId))
                { 
                    CustomJournalStateInternal state =
                        (CustomJournalStateInternal)_customJournaledObjects[persistId]; 
                    Debug.Assert(state != null); 
                    IJournalState customJournalingObject = node as IJournalState;
 
                    //
                    // For below two scenarios, JournalData cannot be restored successfully. For now, we just
                    // simply ignore it and don't throw exception.
                    // 
                    //  A. After the tree was created from xaml/baml stream,  some elements might be replaced
                    //     programatically with new elements which could be created from other xaml/baml by Parser. 
                    // 
                    //  B. If the loose xaml file has been changed since the journal data was created
                    // 
                    //

                    if (customJournalingObject != null)
                    { 
                        customJournalingObject.RestoreJournalState(state);
                    } 
                } 
            }
        } 

        /// 
        /// Walk the logical tree, and perform an operation on all nodes and children of nodes.
        /// This is slightly more complex than it might otherwise be because it makes no assumptions 
        /// that the Logical Tree is strongly typed. It is the responsibility of the operation to make sure
        /// that it can handle the node it receives. 
        ///  
        /// 
        ///  
        private void WalkLogicalTree(object node, NodeOperation operation)
        {
            if (node != null)
            { 
                operation(node);
            } 
 
            DependencyObject treeNode = node as DependencyObject;
            if (treeNode == null) 
            {
                return;
            }
 
            IEnumerator e = LogicalTreeHelper.GetChildren(treeNode).GetEnumerator();
            if (e == null) 
            { 
                return;
            } 

            while (e.MoveNext())
            {
                WalkLogicalTree(e.Current, operation); 
            }
        } 
 
        /// 
        /// Critical - as this modifies Critical data member _subStreams. 
        /// Safe - as this just initializes it to a safe value.
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void Save(Object root) 
        {
            if (_subStreams == null) 
            { 
                _subStreams = new HybridDictionary(3);
            } 
            else
            {
                _subStreams.Clear();
            } 
            WalkLogicalTree(root, new NodeOperation(this.SaveState));
        } 
 
        internal void Load(Object root)
        { 
            if (this.HasAnyData)
            {
                WalkLogicalTree(root, new NodeOperation(this.LoadState));
            } 
        }
 
        ///  
        /// Critical - as this refers to Critical member _subStreams.
        /// Safe - as this doesn't expose the data 
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        internal void Clear()
        { 
            _subStreams = null;
            _customJournaledObjects = null; 
        } 

        #region Private and internal fields and properties 
        private BinaryFormatter Formatter
        {
            get
            { 
                if (_formatter == null)
                { 
                    _formatter = new BinaryFormatter(); 
                }
 
                return _formatter;
            }
        }
 
        [ThreadStatic]
        static private BinaryFormatter _formatter; 
 
        /// 
        /// Critical - This data is critical for two reasons.  One is that this holds 
        ///            data obtained by invoking Serialization under elevation.  The
        ///            other is that we call DeSerialization on this data under elevation.
        /// 
        [SecurityCritical] 
        private HybridDictionary _subStreams = new HybridDictionary(3);
 
        ///  
        /// PersistId->CustomJournalStateInternal map
        /// . 
        /// 
        private HybridDictionary _customJournaledObjects;

        #endregion Private and internal fields and properties 
    }
    #endregion DataStreams class 
 
}

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