PropertyAccessVisitor.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Server / System / Data / Services / Internal / PropertyAccessVisitor.cs / 1407647 / PropertyAccessVisitor.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Visitor to detect and replace access to properties
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Internal
{
    using System.Linq.Expressions; 
    using System.Diagnostics;
    using System.Collections.Generic; 
    using System.Reflection; 
    using System.Data.Services.Providers;
 
    /// Expression visitor class which provides recognission of property access
    /// This class understands all the different ways WCF Data Services can use
    /// to access a property value in the generated query.
    /// The class is meant to be inherited for expression tree processing where 
    /// property accesses are interesting.
    /// Note that it assumes that the expression tree looks the way WCF Data Services generate it. 
    /// Noticable that all the GetValue method calls get the property parameter as a 
    ///  node. This may mean that if there were some rewrites applied
    /// to the tree, the class may not recognize the property accesses anymore. 
    internal abstract class PropertyAccessVisitor : ALinqExpressionVisitor
    {
        /// MethodCallExpression visit method
        /// The MethodCallExpression expression to visit 
        /// The visited MethodCallExpression expression 
        internal override Expression VisitMethodCall(MethodCallExpression m) 
        { 
            string propertyName = null;
            ResourceProperty resourceProperty = null; 

            if ((m.Method.IsGenericMethod &&
                m.Method.GetGenericMethodDefinition() == DataServiceProviderMethods.GetSequenceValueMethodInfo) ||
                (m.Method == DataServiceProviderMethods.GetValueMethodInfo)) 
            {
                // DataServiceProviderMethods.GetSequenceValue(object value, ResourceProperty property) 
                // or 
                // DataServiceProviderMethods.GetValue(object value, ResourceProperty property)
                ConstantExpression propertyExpression = m.Arguments[1] as ConstantExpression; 
                Debug.Assert(
                    propertyExpression != null && propertyExpression.Value is ResourceProperty,
                    "We should have only calls with constant ResourceProperty values.");
                resourceProperty = propertyExpression.Value as ResourceProperty; 
                propertyName = resourceProperty.Name;
            } 
            else if (m.Method == OpenTypeMethods.GetValueOpenPropertyMethodInfo) 
            {
                // OpenTypeMethods.GetValue(object value, string propertyName) 
                ConstantExpression propertyExpression = m.Arguments[1] as ConstantExpression;
                Debug.Assert(
                    propertyExpression != null && propertyExpression.Value is string,
                    "We should have only calls with constant string values."); 
                propertyName = propertyExpression.Value as string;
            } 
 
            if (propertyName != null)
            { 
                Expression operand = m.Arguments[0];
                Expression result = m;
                if (this.ProcessPropertyAccess(propertyName, ref operand, ref result))
                { 
                    if (result == null)
                    { 
                        Debug.Assert( 
                            m.Arguments.Count == 2,
                            "Right now all methods have 2 arguments. If it ever changes this code needs to be modified."); 
                        return Expression.Call(m.Object, m.Method, operand, m.Arguments[1]);
                    }
                    else
                    { 
                        return result;
                    } 
                } 
            }
 
            return base.VisitMethodCall(m);
        }

        ///  
        /// MemberExpression visit method
        ///  
        /// The MemberExpression expression to visit 
        /// The visited MemberExpression expression 
        internal override Expression VisitMemberAccess(MemberExpression m) 
        {
            if (m.Member.MemberType == MemberTypes.Property)
            {
                Expression operand = m.Expression; 
                Expression result = m;
                if (this.ProcessPropertyAccess(m.Member.Name, ref operand, ref result)) 
                { 
                    if (result == null)
                    { 
                        return Expression.MakeMemberAccess(operand, m.Member);
                    }
                    else
                    { 
                        return result;
                    } 
                } 
            }
 
            return base.VisitMemberAccess(m);
        }

        /// Dervied class will override them method to process any property accesses found in the tree. 
        /// The name of the property being accessed.
        /// The expression on which the property is being accessed. 
        /// The implementation may choose to return a different expression through this ref parameter. 
        /// If the method returns true, the  is null and the method
        /// changed this parameter, the caller will replace the operand in the original property 
        /// access with the new expression provided in this parameter. The way the property is accessed
        /// and its name remains the same.
        /// The entire expression of the property access.
        /// The implementation may choose to return a different expression through this ref parameter. 
        /// If the method returns true and this parameter is not null the caller will replace the entire
        /// property access expression with the new one passed in this parameter. 
        /// If the method returns false it means that it is not interested in this property access, 
        /// and the processing of the tree will continue by examining the children of the property access expression.
        /// If the method returns true the caller looks at the returned value of . 
        /// If it is not-null it will replace the entire property access expression with it.
        /// If it's null it will just replace the operand of the property access with the .
        /// If the implementation wants to skip this property access without modification it should return true
        /// and not modify the ref parameters. 
        /// If the method returns true the caller will not continue walking the children of the property
        /// access expression. It's the responsibility of the implementation to do so if it requires such 
        /// functionality. 
        protected abstract bool ProcessPropertyAccess(
            string propertyName, 
            ref Expression operandExpression,
            ref Expression accessExpression);
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Visitor to detect and replace access to properties
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Internal
{
    using System.Linq.Expressions; 
    using System.Diagnostics;
    using System.Collections.Generic; 
    using System.Reflection; 
    using System.Data.Services.Providers;
 
    /// Expression visitor class which provides recognission of property access
    /// This class understands all the different ways WCF Data Services can use
    /// to access a property value in the generated query.
    /// The class is meant to be inherited for expression tree processing where 
    /// property accesses are interesting.
    /// Note that it assumes that the expression tree looks the way WCF Data Services generate it. 
    /// Noticable that all the GetValue method calls get the property parameter as a 
    ///  node. This may mean that if there were some rewrites applied
    /// to the tree, the class may not recognize the property accesses anymore. 
    internal abstract class PropertyAccessVisitor : ALinqExpressionVisitor
    {
        /// MethodCallExpression visit method
        /// The MethodCallExpression expression to visit 
        /// The visited MethodCallExpression expression 
        internal override Expression VisitMethodCall(MethodCallExpression m) 
        { 
            string propertyName = null;
            ResourceProperty resourceProperty = null; 

            if ((m.Method.IsGenericMethod &&
                m.Method.GetGenericMethodDefinition() == DataServiceProviderMethods.GetSequenceValueMethodInfo) ||
                (m.Method == DataServiceProviderMethods.GetValueMethodInfo)) 
            {
                // DataServiceProviderMethods.GetSequenceValue(object value, ResourceProperty property) 
                // or 
                // DataServiceProviderMethods.GetValue(object value, ResourceProperty property)
                ConstantExpression propertyExpression = m.Arguments[1] as ConstantExpression; 
                Debug.Assert(
                    propertyExpression != null && propertyExpression.Value is ResourceProperty,
                    "We should have only calls with constant ResourceProperty values.");
                resourceProperty = propertyExpression.Value as ResourceProperty; 
                propertyName = resourceProperty.Name;
            } 
            else if (m.Method == OpenTypeMethods.GetValueOpenPropertyMethodInfo) 
            {
                // OpenTypeMethods.GetValue(object value, string propertyName) 
                ConstantExpression propertyExpression = m.Arguments[1] as ConstantExpression;
                Debug.Assert(
                    propertyExpression != null && propertyExpression.Value is string,
                    "We should have only calls with constant string values."); 
                propertyName = propertyExpression.Value as string;
            } 
 
            if (propertyName != null)
            { 
                Expression operand = m.Arguments[0];
                Expression result = m;
                if (this.ProcessPropertyAccess(propertyName, ref operand, ref result))
                { 
                    if (result == null)
                    { 
                        Debug.Assert( 
                            m.Arguments.Count == 2,
                            "Right now all methods have 2 arguments. If it ever changes this code needs to be modified."); 
                        return Expression.Call(m.Object, m.Method, operand, m.Arguments[1]);
                    }
                    else
                    { 
                        return result;
                    } 
                } 
            }
 
            return base.VisitMethodCall(m);
        }

        ///  
        /// MemberExpression visit method
        ///  
        /// The MemberExpression expression to visit 
        /// The visited MemberExpression expression 
        internal override Expression VisitMemberAccess(MemberExpression m) 
        {
            if (m.Member.MemberType == MemberTypes.Property)
            {
                Expression operand = m.Expression; 
                Expression result = m;
                if (this.ProcessPropertyAccess(m.Member.Name, ref operand, ref result)) 
                { 
                    if (result == null)
                    { 
                        return Expression.MakeMemberAccess(operand, m.Member);
                    }
                    else
                    { 
                        return result;
                    } 
                } 
            }
 
            return base.VisitMemberAccess(m);
        }

        /// Dervied class will override them method to process any property accesses found in the tree. 
        /// The name of the property being accessed.
        /// The expression on which the property is being accessed. 
        /// The implementation may choose to return a different expression through this ref parameter. 
        /// If the method returns true, the  is null and the method
        /// changed this parameter, the caller will replace the operand in the original property 
        /// access with the new expression provided in this parameter. The way the property is accessed
        /// and its name remains the same.
        /// The entire expression of the property access.
        /// The implementation may choose to return a different expression through this ref parameter. 
        /// If the method returns true and this parameter is not null the caller will replace the entire
        /// property access expression with the new one passed in this parameter. 
        /// If the method returns false it means that it is not interested in this property access, 
        /// and the processing of the tree will continue by examining the children of the property access expression.
        /// If the method returns true the caller looks at the returned value of . 
        /// If it is not-null it will replace the entire property access expression with it.
        /// If it's null it will just replace the operand of the property access with the .
        /// If the implementation wants to skip this property access without modification it should return true
        /// and not modify the ref parameters. 
        /// If the method returns true the caller will not continue walking the children of the property
        /// access expression. It's the responsibility of the implementation to do so if it requires such 
        /// functionality. 
        protected abstract bool ProcessPropertyAccess(
            string propertyName, 
            ref Expression operandExpression,
            ref Expression accessExpression);
    }
} 

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