ProjectionPathBuilder.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / ProjectionPathBuilder.cs / 1305376 / ProjectionPathBuilder.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
// Provides a class that can materialize ATOM entries into typed
// objects, while maintaining a log of changes done. 
//  
//---------------------------------------------------------------------
 
namespace System.Data.Services.Client
{
    #region Namespaces.
 
    using System;
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.Linq;
    using System.Linq.Expressions; 

    #endregion Namespaces.

    ///  
    /// Use this class to help keep track of projection paths built
    /// while compiling a projection-based materialization plan. 
    ///  
    internal class ProjectionPathBuilder
    { 
        #region Private fields.

        /// Stack of whether entities are in scope.
        private readonly Stack entityInScope; 

        /// Registers rewrites for member initialization blocks. 
        private readonly List rewrites; 

        /// Stack of lambda expressions in scope. 
        private readonly Stack parameterExpressions;

        /// 
        /// Stack of expected type expression for . 
        /// 
        private readonly Stack parameterExpressionTypes; 
 
        /// Stack of 'entry' parameter expressions.
        private readonly Stack parameterEntries; 

        /// Stack of projection (target-tree) types for parameters.
        private readonly Stack parameterProjectionTypes;
 
        #endregion Private fields.
 
        #region Constructors. 

        /// Initializes a new  instance. 
        internal ProjectionPathBuilder()
        {
            this.entityInScope = new Stack();
            this.rewrites = new List(); 
            this.parameterExpressions = new Stack();
            this.parameterExpressionTypes = new Stack(); 
            this.parameterEntries = new Stack(); 
            this.parameterProjectionTypes = new Stack();
        } 

        #endregion Constructors.

        #region Internal properties. 

        /// Whether the current scope is acting on an entity. 
        internal bool CurrentIsEntity 
        {
            get { return this.entityInScope.Peek(); } 
        }

        /// Expression for the expected type parameter.
        internal Expression ExpectedParamTypeInScope 
        {
            get 
            { 
                Debug.Assert(this.parameterExpressionTypes.Count > 0, "this.parameterExpressionTypes.Count > 0");
                return this.parameterExpressionTypes.Peek(); 
            }
        }

        /// Whether any rewrites have been registered. 
        internal bool HasRewrites
        { 
            get { return this.rewrites.Count > 0; } 
        }
 
        /// Expression for the entity parameter in the source tree lambda.
        internal Expression LambdaParameterInScope
        {
            get 
            {
                return this.parameterExpressions.Peek(); 
            } 
        }
 
        /// Expression for the entry parameter in the target tree.
        internal Expression ParameterEntryInScope
        {
            get 
            {
                return this.parameterEntries.Peek(); 
            } 
        }
 
        #endregion Internal properties.

        #region Methods.
 
        /// Provides a string representation of this object.
        /// String representation of this object. 
        public override string ToString() 
        {
            string result = "ProjectionPathBuilder: "; 
            if (this.parameterExpressions.Count == 0)
            {
                result += "(empty)";
            } 
            else
            { 
                result += 
                    "entity:" + this.CurrentIsEntity +
                    " param:" + this.ParameterEntryInScope; 
            }

            return result;
        } 

        /// Records that a lambda scope has been entered when visiting a projection. 
        /// Lambda being visited. 
        /// Expression to the entry parameter from the target tree.
        /// Expression to the entry-expected-type from the target tree. 
        internal void EnterLambdaScope(LambdaExpression lambda, Expression entry, Expression expectedType)
        {
            Debug.Assert(lambda != null, "lambda != null");
            Debug.Assert(lambda.Parameters.Count == 1, "lambda.Parameters.Count == 1"); 

            ParameterExpression param = lambda.Parameters[0]; 
            Type projectionType = lambda.Body.Type; 
            bool isEntityType = ClientType.CheckElementTypeIsEntity(projectionType);
 
            this.entityInScope.Push(isEntityType);
            this.parameterExpressions.Push(param);
            this.parameterExpressionTypes.Push(expectedType);
            this.parameterEntries.Push(entry); 
            this.parameterProjectionTypes.Push(projectionType);
        } 
 
        /// 
        /// Records that a member initialization expression has been entered 
        /// when visting a projection.
        /// 
        /// Expression for initialization.
        internal void EnterMemberInit(MemberInitExpression init) 
        {
            bool isEntityType = ClientType.CheckElementTypeIsEntity(init.Type); 
            this.entityInScope.Push(isEntityType); 
        }
 
        /// Gets a rewrite for the specified expression; null if none is found.
        /// Expression to match.
        /// A rewrite for the expression; possibly null.
        internal Expression GetRewrite(Expression expression) 
        {
            Debug.Assert(expression != null, "expression != null"); 
 
            List names = new List();
            while (expression.NodeType == ExpressionType.MemberAccess) 
            {
                MemberExpression member = (MemberExpression)expression;
                names.Add(member.Member.Name);
                expression = member.Expression; 
            }
 
            Expression result = null; 
            foreach (var rewrite in this.rewrites)
            { 
                if (rewrite.Root != expression)
                {
                    continue;
                } 

                if (names.Count != rewrite.MemberNames.Length) 
                { 
                    continue;
                } 

                bool match = true;
                for (int i = 0; i < names.Count && i < rewrite.MemberNames.Length; i++)
                { 
                    if (names[names.Count - i - 1] != rewrite.MemberNames[i])
                    { 
                        match = false; 
                        break;
                    } 
                }

                if (match)
                { 
                    result = rewrite.RewriteExpression;
                    break; 
                } 
            }
 
            return result;
        }

        /// Records that a lambda scope has been left when visting a projection. 
        internal void LeaveLambdaScope()
        { 
            this.entityInScope.Pop(); 
            this.parameterExpressions.Pop();
            this.parameterExpressionTypes.Pop(); 
            this.parameterEntries.Pop();
            this.parameterProjectionTypes.Pop();
        }
 
        /// 
        /// Records that a member initialization expression has been left when 
        /// visting a projection. 
        /// 
        internal void LeaveMemberInit() 
        {
            this.entityInScope.Pop();
        }
 
        /// Registers a member initialization rewrite.
        /// Root of member access path, typically a source tree parameter of entity type. 
        /// Sequence of names to match. 
        /// Rewrite expression for names.
        internal void RegisterRewrite(Expression root, string[] names, Expression rewriteExpression) 
        {
            Debug.Assert(root != null, "root != null");
            Debug.Assert(names != null, "names != null");
            Debug.Assert(rewriteExpression != null, "rewriteExpression != null"); 

            this.rewrites.Add(new MemberInitRewrite() { Root = root, MemberNames = names, RewriteExpression = rewriteExpression }); 
            this.parameterEntries.Push(rewriteExpression); 
        }
 
        /// Revokes the latest rewrite registered on the specified .
        /// Root of rewrites to revoke.
        /// Names to revoke.
        internal void RevokeRewrite(Expression root, string[] names) 
        {
            Debug.Assert(root != null, "root != null"); 
 
            for (int i = 0; i < this.rewrites.Count; i++)
            { 
                if (this.rewrites[i].Root != root)
                {
                    continue;
                } 

                if (names.Length != this.rewrites[i].MemberNames.Length) 
                { 
                    continue;
                } 

                bool match = true;
                for (int j = 0; j < names.Length; j++)
                { 
                    if (names[j] != this.rewrites[i].MemberNames[j])
                    { 
                        match = false; 
                        break;
                    } 
                }

                if (match)
                { 
                    this.rewrites.RemoveAt(i);
                    this.parameterEntries.Pop(); 
                    return; 
                }
            } 
        }

        #endregion Methods.
 
        #region Inner types.
 
        /// Use this class to record how rewrites should occur under nested member initializations. 
        internal class MemberInitRewrite
        { 
            /// Sequence of member names to match.
            internal string[] MemberNames
            {
                get; 
                set;
            } 
 
            /// Root of member access path, typically a source tree parameter of entity type.
            internal Expression Root 
            {
                get;
                set;
            } 

            /// Rewrite expressions for the last member path. 
            internal Expression RewriteExpression 
            {
                get; 
                set;
            }
        }
 
        #endregion Inner types.
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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