InputBinder.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / ALinq / InputBinder.cs / 1 / InputBinder.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Expression visitor that converts ParameterReference or (MemberAccess*)\ParameterReference expressions
//      into references to one or more ResourceSetExpressions. After processing, the specified expression tree 
//      will contain InputReferenceExpressions instead of these parameter or parameter and property references. 
// 
// 
// @owner  [....]
//---------------------------------------------------------------------
namespace System.Data.Services.Client
{ 
    using System;
    using System.Collections.Generic; 
    using System.Text; 
    using System.Linq;
    using System.Linq.Expressions; 
    using System.Reflection;
    using System.Diagnostics;

    ///  
    /// Replaces references to resource sets - represented as either ParameterExpressions or one or more
    /// MemberExpressions over a ParameterExpression - with an appropriate InputReferenceExpression that 
    /// indicates which resource set is referenced; effective 'binds' the argument expression to the 
    /// resource sets that it references.
    ///  
    internal sealed class InputBinder : DataServiceExpressionVisitor
    {
        /// Tracks which resource sets are referenced by the argument expression
        private readonly HashSet referencedInputs = new HashSet(EqualityComparer.Default); 

        /// Resource from which valid references must start; if no set with a transparent scope is present, only direct references to this resource will be rebound 
        private readonly ResourceExpression input; 

        /// The input resource, as a resource set (may be null if the input is actually a NavigationPropertySingletonExpression) 
        private readonly ResourceSetExpression inputSet;

        /// The ParameterExpression that, if encountered, indicates a reference to the input resource set
        private readonly ParameterExpression inputParameter; 

        ///  
        /// Constructs a new InputBinder based on the specified input resource set, which is represented by the specified ParameterExpression. 
        /// 
        /// The current input resource from which valid references must start 
        /// The parameter that must be referenced in order to refer to the specified input resource set
        private InputBinder(ResourceExpression resource, ParameterExpression setReferenceParam)
        {
            this.input = resource; 
            this.inputSet = resource as ResourceSetExpression;
            this.inputParameter = setReferenceParam; 
        } 

        ///  
        /// Replaces Lambda parameter references or transparent scope property accesses over those Lambda
        /// parameter references with s to the appropriate corresponding
        /// s, based on the 'input' ResourceSetExpression to which the
        /// Lambda is logically applied and any enclosing transparent scope applied to that input resource set. 
        /// 
        /// The parameter to rebind 
        ///  
        /// The 'current input' resource set - either the root resource set or the
        /// rightmost set in the navigation chain. 
        /// The Lambda parameter that represents a reference to the 'input' set
        /// A list that will be populated with the resource sets that were referenced by the rebound expression
        /// 
        /// The rebound version of  where MemberExpression/ParameterExpressions that 
        /// represent resource set references have been replaced with appropriate InputReferenceExpressions.
        ///  
        internal static Expression Bind(Expression e, ResourceExpression currentInput, ParameterExpression inputParameter, List referencedInputs) 
        {
            Debug.Assert(e != null, "Expression cannot be null"); 
            Debug.Assert(currentInput != null, "A current input resource set is required");
            Debug.Assert(inputParameter != null, "The input lambda parameter is required");
            Debug.Assert(referencedInputs != null, "The referenced inputs list is required");
 
            InputBinder binder = new InputBinder(currentInput, inputParameter);
            e = binder.Visit(e); 
            referencedInputs.AddRange(binder.referencedInputs); 
            return e;
        } 

        /// 
        /// Resolves member accesses that represent transparent scope property accesses to the corresponding resource set,
        /// iff the input resource set is enclosed in a transparent scope and the specified MemberExpression represents 
        /// such a property access.
        ///  
        /// MemberExpression expression to visit 
        /// 
        /// An InputReferenceExpression if the member access represents a transparent scope property 
        /// access that can be resolved to a resource set in the path that produces the input resource set;
        /// otherwise the same MemberExpression is returned.
        /// 
        internal override Expression VisitMemberAccess(MemberExpression m) 
        {
            // If the current input resource set is not enclosed in a transparent scope, then this 
            // MemberExpression cannot represent a valid transparent scope access based on the input parameter. 
            if (this.inputSet == null ||
                !this.inputSet.HasTransparentScope) 
            {
                return base.VisitMemberAccess(m);
            }
 
            ParameterExpression innerParamRef = null;
            Stack nestedAccesses = new Stack(); 
            MemberExpression memberRef = m; 
            while (memberRef != null &&
                   memberRef.Member.MemberType == MemberTypes.Property && 
                   memberRef.Expression != null)
            {
                nestedAccesses.Push((PropertyInfo)memberRef.Member);
 
                if (memberRef.Expression != null && memberRef.Expression.NodeType == ExpressionType.Parameter)
                { 
                    innerParamRef = (ParameterExpression)memberRef.Expression; 
                }
 
                memberRef = memberRef.Expression as MemberExpression;
            }

            // Only continue if the inner non-MemberExpression is the input reference ParameterExpression and 
            // at least one property reference is present - otherwise this cannot be a transparent scope access.
            if (innerParamRef == this.inputParameter && nestedAccesses.Count > 0) 
            { 
                ResourceExpression target = this.input;
                ResourceSetExpression targetSet = this.inputSet; 
                Expression retExpr = null;
                while (nestedAccesses.Count > 0)
                {
                    PropertyInfo currentProp = nestedAccesses.Pop(); 

                    if (retExpr == null && targetSet != null && targetSet.HasTransparentScope) 
                    { 
                        if (currentProp.Name.Equals(targetSet.TransparentScope.Accessor, StringComparison.Ordinal))
                        { 
                            retExpr = this.CreateReference(targetSet);
                        }
                        else
                        { 
                            if (currentProp.Name.Equals(targetSet.TransparentScope.SourceAccessor, StringComparison.Ordinal))
                            { 
                                target = (ResourceExpression)targetSet.Source; 
                                targetSet = target as ResourceSetExpression;
                                if (targetSet == null || !targetSet.HasTransparentScope) 
                                {
                                    retExpr = this.CreateReference(target);
                                }
                            } 
                            else
                            { 
                                // The property reference is not to the resource set or it's source resource set. 
                                // This implies the transparent scope is not actually a transparent scope but a row constructor,
                                // and is not supported. 
                                return m;
                            }
                        }
                    } 
                    else
                    { 
                        retExpr = Expression.Property(retExpr, currentProp); 
                    }
                } 

                return retExpr;
            }
 
            return m;
        } 
 
        /// 
        /// Converts a parameter reference to the input resource set into an InputReferenceExpression, 
        /// iff the parameter reference is to the parameter expression that represents the input resource set
        /// and the input resource set is not enclosed in a transparent scope.
        /// 
        /// The parameter reference expression 
        /// 
        /// An InputReferenceExpression if the parameter reference is to the input parameter; 
        /// otherwise the same parameter reference expression 
        /// 
        internal override Expression VisitParameter(ParameterExpression p) 
        {
            // If the input Resource Set is not enclosed in a transparent scope,
            // and the parameter reference is a reference to the Lambda parameter
            // that represents the input resource set, then return an InputReferenceExpression. 
            if ((this.inputSet == null || !this.inputSet.HasTransparentScope) &&
               p == this.inputParameter) 
            { 
                return this.CreateReference(this.input);
            } 
            else
            {
                return base.VisitParameter(p);
            } 
        }
 
        ///  
        /// Returns an  that references the specified resource set,
        /// and also adds the the resource set to the hashset of resource sets that were referenced by the 
        /// expression that is being rebound.
        /// 
        /// The resource(set) for which a reference was found
        /// An InputReferenceExpression that represents a reference to the specified resource set 
        private Expression CreateReference(ResourceExpression resource)
        { 
            this.referencedInputs.Add(resource); 
            return resource.CreateReference();
        } 
    }
}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Expression visitor that converts ParameterReference or (MemberAccess*)\ParameterReference expressions
//      into references to one or more ResourceSetExpressions. After processing, the specified expression tree 
//      will contain InputReferenceExpressions instead of these parameter or parameter and property references. 
// 
// 
// @owner  [....]
//---------------------------------------------------------------------
namespace System.Data.Services.Client
{ 
    using System;
    using System.Collections.Generic; 
    using System.Text; 
    using System.Linq;
    using System.Linq.Expressions; 
    using System.Reflection;
    using System.Diagnostics;

    ///  
    /// Replaces references to resource sets - represented as either ParameterExpressions or one or more
    /// MemberExpressions over a ParameterExpression - with an appropriate InputReferenceExpression that 
    /// indicates which resource set is referenced; effective 'binds' the argument expression to the 
    /// resource sets that it references.
    ///  
    internal sealed class InputBinder : DataServiceExpressionVisitor
    {
        /// Tracks which resource sets are referenced by the argument expression
        private readonly HashSet referencedInputs = new HashSet(EqualityComparer.Default); 

        /// Resource from which valid references must start; if no set with a transparent scope is present, only direct references to this resource will be rebound 
        private readonly ResourceExpression input; 

        /// The input resource, as a resource set (may be null if the input is actually a NavigationPropertySingletonExpression) 
        private readonly ResourceSetExpression inputSet;

        /// The ParameterExpression that, if encountered, indicates a reference to the input resource set
        private readonly ParameterExpression inputParameter; 

        ///  
        /// Constructs a new InputBinder based on the specified input resource set, which is represented by the specified ParameterExpression. 
        /// 
        /// The current input resource from which valid references must start 
        /// The parameter that must be referenced in order to refer to the specified input resource set
        private InputBinder(ResourceExpression resource, ParameterExpression setReferenceParam)
        {
            this.input = resource; 
            this.inputSet = resource as ResourceSetExpression;
            this.inputParameter = setReferenceParam; 
        } 

        ///  
        /// Replaces Lambda parameter references or transparent scope property accesses over those Lambda
        /// parameter references with s to the appropriate corresponding
        /// s, based on the 'input' ResourceSetExpression to which the
        /// Lambda is logically applied and any enclosing transparent scope applied to that input resource set. 
        /// 
        /// The parameter to rebind 
        ///  
        /// The 'current input' resource set - either the root resource set or the
        /// rightmost set in the navigation chain. 
        /// The Lambda parameter that represents a reference to the 'input' set
        /// A list that will be populated with the resource sets that were referenced by the rebound expression
        /// 
        /// The rebound version of  where MemberExpression/ParameterExpressions that 
        /// represent resource set references have been replaced with appropriate InputReferenceExpressions.
        ///  
        internal static Expression Bind(Expression e, ResourceExpression currentInput, ParameterExpression inputParameter, List referencedInputs) 
        {
            Debug.Assert(e != null, "Expression cannot be null"); 
            Debug.Assert(currentInput != null, "A current input resource set is required");
            Debug.Assert(inputParameter != null, "The input lambda parameter is required");
            Debug.Assert(referencedInputs != null, "The referenced inputs list is required");
 
            InputBinder binder = new InputBinder(currentInput, inputParameter);
            e = binder.Visit(e); 
            referencedInputs.AddRange(binder.referencedInputs); 
            return e;
        } 

        /// 
        /// Resolves member accesses that represent transparent scope property accesses to the corresponding resource set,
        /// iff the input resource set is enclosed in a transparent scope and the specified MemberExpression represents 
        /// such a property access.
        ///  
        /// MemberExpression expression to visit 
        /// 
        /// An InputReferenceExpression if the member access represents a transparent scope property 
        /// access that can be resolved to a resource set in the path that produces the input resource set;
        /// otherwise the same MemberExpression is returned.
        /// 
        internal override Expression VisitMemberAccess(MemberExpression m) 
        {
            // If the current input resource set is not enclosed in a transparent scope, then this 
            // MemberExpression cannot represent a valid transparent scope access based on the input parameter. 
            if (this.inputSet == null ||
                !this.inputSet.HasTransparentScope) 
            {
                return base.VisitMemberAccess(m);
            }
 
            ParameterExpression innerParamRef = null;
            Stack nestedAccesses = new Stack(); 
            MemberExpression memberRef = m; 
            while (memberRef != null &&
                   memberRef.Member.MemberType == MemberTypes.Property && 
                   memberRef.Expression != null)
            {
                nestedAccesses.Push((PropertyInfo)memberRef.Member);
 
                if (memberRef.Expression != null && memberRef.Expression.NodeType == ExpressionType.Parameter)
                { 
                    innerParamRef = (ParameterExpression)memberRef.Expression; 
                }
 
                memberRef = memberRef.Expression as MemberExpression;
            }

            // Only continue if the inner non-MemberExpression is the input reference ParameterExpression and 
            // at least one property reference is present - otherwise this cannot be a transparent scope access.
            if (innerParamRef == this.inputParameter && nestedAccesses.Count > 0) 
            { 
                ResourceExpression target = this.input;
                ResourceSetExpression targetSet = this.inputSet; 
                Expression retExpr = null;
                while (nestedAccesses.Count > 0)
                {
                    PropertyInfo currentProp = nestedAccesses.Pop(); 

                    if (retExpr == null && targetSet != null && targetSet.HasTransparentScope) 
                    { 
                        if (currentProp.Name.Equals(targetSet.TransparentScope.Accessor, StringComparison.Ordinal))
                        { 
                            retExpr = this.CreateReference(targetSet);
                        }
                        else
                        { 
                            if (currentProp.Name.Equals(targetSet.TransparentScope.SourceAccessor, StringComparison.Ordinal))
                            { 
                                target = (ResourceExpression)targetSet.Source; 
                                targetSet = target as ResourceSetExpression;
                                if (targetSet == null || !targetSet.HasTransparentScope) 
                                {
                                    retExpr = this.CreateReference(target);
                                }
                            } 
                            else
                            { 
                                // The property reference is not to the resource set or it's source resource set. 
                                // This implies the transparent scope is not actually a transparent scope but a row constructor,
                                // and is not supported. 
                                return m;
                            }
                        }
                    } 
                    else
                    { 
                        retExpr = Expression.Property(retExpr, currentProp); 
                    }
                } 

                return retExpr;
            }
 
            return m;
        } 
 
        /// 
        /// Converts a parameter reference to the input resource set into an InputReferenceExpression, 
        /// iff the parameter reference is to the parameter expression that represents the input resource set
        /// and the input resource set is not enclosed in a transparent scope.
        /// 
        /// The parameter reference expression 
        /// 
        /// An InputReferenceExpression if the parameter reference is to the input parameter; 
        /// otherwise the same parameter reference expression 
        /// 
        internal override Expression VisitParameter(ParameterExpression p) 
        {
            // If the input Resource Set is not enclosed in a transparent scope,
            // and the parameter reference is a reference to the Lambda parameter
            // that represents the input resource set, then return an InputReferenceExpression. 
            if ((this.inputSet == null || !this.inputSet.HasTransparentScope) &&
               p == this.inputParameter) 
            { 
                return this.CreateReference(this.input);
            } 
            else
            {
                return base.VisitParameter(p);
            } 
        }
 
        ///  
        /// Returns an  that references the specified resource set,
        /// and also adds the the resource set to the hashset of resource sets that were referenced by the 
        /// expression that is being rebound.
        /// 
        /// The resource(set) for which a reference was found
        /// An InputReferenceExpression that represents a reference to the specified resource set 
        private Expression CreateReference(ResourceExpression resource)
        { 
            this.referencedInputs.Add(resource); 
            return resource.CreateReference();
        } 
    }
}


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