ExpressionVisitor.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 / Core / Microsoft / Scripting / Ast / ExpressionVisitor.cs / 1305376 / ExpressionVisitor.cs

                            /* **************************************************************************** 
 *
 * Copyright (c) Microsoft Corporation.
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 * 
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/ 

using System.Collections.ObjectModel; 
using System.Diagnostics; 
using System.Dynamic.Utils;
using System.Runtime.CompilerServices; 

#if SILVERLIGHT
using System.Core;
#endif 

namespace System.Linq.Expressions { 
 
    /// 
    /// Represents a visitor or rewriter for expression trees. 
    /// 
    /// 
    /// This class is designed to be inherited to create more specialized
    /// classes whose functionality requires traversing, examining or copying 
    /// an expression tree.
    ///  
    public abstract class ExpressionVisitor { 

        ///  
        /// Initializes a new instance of .
        /// 
        protected ExpressionVisitor() {
        } 

        ///  
        /// Dispatches the expression to one of the more specialized visit methods in this class. 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        public virtual Expression Visit(Expression node) {
            if (node != null) { 
                return node.Accept(this);
            } 
            return null; 
        }
 
        /// 
        /// Dispatches the list of expressions to one of the more specialized visit methods in this class.
        /// 
        /// The expressions to visit. 
        /// The modified expression list, if any of the elements were modified;
        /// otherwise, returns the original expression list. 
        public ReadOnlyCollection Visit(ReadOnlyCollection nodes) { 
            Expression[] newNodes = null;
            for (int i = 0, n = nodes.Count; i < n; i++) { 
                Expression node = Visit(nodes[i]);

                if (newNodes != null) {
                    newNodes[i] = node; 
                } else if (!object.ReferenceEquals(node, nodes[i])) {
                    newNodes = new Expression[n]; 
                    for (int j = 0; j < i; j++) { 
                        newNodes[j] = nodes[j];
                    } 
                    newNodes[i] = node;
                }
            }
            if (newNodes == null) { 
                return nodes;
            } 
            return new TrueReadOnlyCollection(newNodes); 
        }
 
        internal Expression[] VisitArguments(IArgumentProvider nodes) {
            Expression[] newNodes = null;
            for (int i = 0, n = nodes.ArgumentCount; i < n; i++) {
                Expression curNode = nodes.GetArgument(i); 
                Expression node = Visit(curNode);
 
                if (newNodes != null) { 
                    newNodes[i] = node;
                } else if (!object.ReferenceEquals(node, curNode)) { 
                    newNodes = new Expression[n];
                    for (int j = 0; j < i; j++) {
                        newNodes[j] = nodes.GetArgument(j);
                    } 
                    newNodes[i] = node;
                } 
            } 
            return newNodes;
        } 

        /// 
        /// Visits all nodes in the collection using a specified element visitor.
        ///  
        /// The type of the nodes.
        /// The nodes to visit. 
        /// A delegate that visits a single element, 
        /// optionally replacing it with a new element.
        /// The modified node list, if any of the elements were modified; 
        /// otherwise, returns the original node list.
        public static ReadOnlyCollection Visit(ReadOnlyCollection nodes, Func elementVisitor) {
            T[] newNodes = null;
            for (int i = 0, n = nodes.Count; i < n; i++) { 
                T node = elementVisitor(nodes[i]);
                if (newNodes != null) { 
                    newNodes[i] = node; 
                } else if (!object.ReferenceEquals(node, nodes[i])) {
                    newNodes = new T[n]; 
                    for (int j = 0; j < i; j++) {
                        newNodes[j] = nodes[j];
                    }
                    newNodes[i] = node; 
                }
            } 
            if (newNodes == null) { 
                return nodes;
            } 
            return new TrueReadOnlyCollection(newNodes);
        }

        ///  
        /// Visits an expression, casting the result back to the original expression type.
        ///  
        /// The type of the expression. 
        /// The expression to visit.
        /// The name of the calling method; used to report to report a better error message. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        /// The visit method for this node returned a different type.
        public T VisitAndConvert(T node, string callerName) where T : Expression { 
            if (node == null) {
                return null; 
            } 
            node = Visit(node) as T;
            if (node == null) { 
                throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName);
            }
            return node;
        } 

        ///  
        /// Visits an expression, casting the result back to the original expression type. 
        /// 
        /// The type of the expression. 
        /// The expression to visit.
        /// The name of the calling method; used to report to report a better error message.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        /// The visit method for this node returned a different type.
        public ReadOnlyCollection VisitAndConvert(ReadOnlyCollection nodes, string callerName) where T : Expression { 
            T[] newNodes = null; 
            for (int i = 0, n = nodes.Count; i < n; i++) {
                T node = Visit(nodes[i]) as T; 
                if (node == null) {
                    throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName);
                }
 
                if (newNodes != null) {
                    newNodes[i] = node; 
                } else if (!object.ReferenceEquals(node, nodes[i])) { 
                    newNodes = new T[n];
                    for (int j = 0; j < i; j++) { 
                        newNodes[j] = nodes[j];
                    }
                    newNodes[i] = node;
                } 
            }
            if (newNodes == null) { 
                return nodes; 
            }
            return new TrueReadOnlyCollection(newNodes); 
        }

        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitBinary(BinaryExpression node) { 
            // Walk children in evaluation order: left, conversion, right
            return ValidateBinary(
                node,
                node.Update( 
                    Visit(node.Left),
                    VisitAndConvert(node.Conversion, "VisitBinary"), 
                    Visit(node.Right) 
                )
            ); 
        }

        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitBlock(BlockExpression node) { 
            int count = node.ExpressionCount;
            Expression[] nodes = null;
            for (int i = 0; i < count; i++) {
                Expression oldNode = node.GetExpression(i); 
                Expression newNode = Visit(oldNode);
 
                if (oldNode != newNode) { 
                    if (nodes == null) {
                        nodes = new Expression[count]; 
                    }
                    nodes[i] = newNode;
                }
            } 
            var v = VisitAndConvert(node.Variables, "VisitBlock");
 
            if (v == node.Variables && nodes == null) { 
                return node;
            } else { 
                for (int i = 0; i < count; i++) {
                    if (nodes[i] == null) {
                        nodes[i] = node.GetExpression(i);
                    } 
                }
            } 
 
            return node.Rewrite(v, nodes);
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitConditional(ConditionalExpression node) {
            return node.Update(Visit(node.Test), Visit(node.IfTrue), Visit(node.IfFalse)); 
        }

        /// 
        /// Visits the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitConstant(ConstantExpression node) { 
            return node;
        }

        ///  
        /// Visits the .
        ///  
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitDebugInfo(DebugInfoExpression node) {
            return node;
        }
 
        /// 
        /// Visits the children of the . 
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitDynamic(DynamicExpression node) {
            Expression[] a = VisitArguments((IArgumentProvider)node);
            if (a == null) { 
                return node;
            } 
 
            return node.Rewrite(a);
        } 

        /// 
        /// Visits the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitDefault(DefaultExpression node) {
            return node; 
        }

        /// 
        /// Visits the children of the extension expression. 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        ///  
        /// This can be overridden to visit or rewrite specific extension nodes.
        /// If it is not overridden, this method will call ,
        /// which gives the node a chance to walk its children. By default,
        ///  will try to reduce the node. 
        /// 
        protected internal virtual Expression VisitExtension(Expression node) { 
            return node.VisitChildren(this); 
        }
 
        /// 
        /// Visits the children of the .
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitGoto(GotoExpression node) { 
            return node.Update(VisitLabelTarget(node.Target), Visit(node.Value));
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitInvocation(InvocationExpression node) {
            Expression e = Visit(node.Expression); 
            Expression[] a = VisitArguments(node);
            if (e == node.Expression && a == null) {
                return node;
            } 

            return node.Rewrite(e, a); 
        } 

        ///  
        /// Visits the .
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected virtual LabelTarget VisitLabelTarget(LabelTarget node) { 
            return node; 
        }
 
        /// 
        /// Visits the children of the .
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitLabel(LabelExpression node) { 
            return node.Update(VisitLabelTarget(node.Target), Visit(node.DefaultValue));
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The type of the delegate.
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitLambda(Expression node) { 
            return node.Update(Visit(node.Body), VisitAndConvert(node.Parameters, "VisitLambda"));
        }

        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitLoop(LoopExpression node) {
            return node.Update(VisitLabelTarget(node.BreakLabel), VisitLabelTarget(node.ContinueLabel), Visit(node.Body));
        }
 
        /// 
        /// Visits the children of the . 
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitMember(MemberExpression node) {
            return node.Update(Visit(node.Expression));
        } 

        ///  
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitIndex(IndexExpression node) {
            Expression o = Visit(node.Object); 
            Expression[] a = VisitArguments(node);
            if (o == node.Object && a == null) { 
                return node; 
            }
 
            return node.Rewrite(o, a);
        }

        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitMethodCall(MethodCallExpression node) {
            Expression o = Visit(node.Object);
            Expression[] a = VisitArguments((IArgumentProvider)node);
            if (o == node.Object && a == null) { 
                return node;
            } 
 
            return node.Rewrite(o, a);
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitNewArray(NewArrayExpression node) {
            return node.Update(Visit(node.Expressions)); 
        }

        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] 
        protected internal virtual Expression VisitNew(NewExpression node) {
            return node.Update(Visit(node.Arguments));
        }
 
        /// 
        /// Visits the . 
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitParameter(ParameterExpression node) {
            return node;
        } 

        ///  
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {
            return node.Update(VisitAndConvert(node.Variables, "VisitRuntimeVariables")); 
        }
 
        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected virtual SwitchCase VisitSwitchCase(SwitchCase node) { 
            return node.Update(Visit(node.TestValues), Visit(node.Body));
        } 
 
        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitSwitch(SwitchExpression node) {
            return ValidateSwitch( 
                node, 
                node.Update(
                    Visit(node.SwitchValue), 
                    Visit(node.Cases, VisitSwitchCase),
                    Visit(node.DefaultBody)
                )
            ); 
        }
 
        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected virtual CatchBlock VisitCatchBlock(CatchBlock node) { 
            return node.Update(VisitAndConvert(node.Variable, "VisitCatchBlock"), Visit(node.Filter), Visit(node.Body));
        } 
 
        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitTry(TryExpression node) {
            return node.Update( 
                Visit(node.Body), 
                Visit(node.Handlers, VisitCatchBlock),
                Visit(node.Finally), 
                Visit(node.Fault)
            );
        }
 
        /// 
        /// Visits the children of the . 
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitTypeBinary(TypeBinaryExpression node) {
            return node.Update(Visit(node.Expression));
        } 

        ///  
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitUnary(UnaryExpression node) {
            return ValidateUnary(node, node.Update(Visit(node.Operand))); 
        }
 
        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitMemberInit(MemberInitExpression node) { 
            return node.Update(
                VisitAndConvert(node.NewExpression, "VisitMemberInit"), 
                Visit(node.Bindings, VisitMemberBinding) 
            );
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitListInit(ListInitExpression node) {
            return node.Update( 
                VisitAndConvert(node.NewExpression, "VisitListInit"),
                Visit(node.Initializers, VisitElementInit)
            );
        } 

        ///  
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected virtual ElementInit VisitElementInit(ElementInit node) {
            return node.Update(Visit(node.Arguments)); 
        }
 
        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected virtual MemberBinding VisitMemberBinding(MemberBinding node) { 
            switch (node.BindingType) {
                case MemberBindingType.Assignment: 
                    return VisitMemberAssignment((MemberAssignment)node); 
                case MemberBindingType.MemberBinding:
                    return VisitMemberMemberBinding((MemberMemberBinding)node); 
                case MemberBindingType.ListBinding:
                    return VisitMemberListBinding((MemberListBinding)node);
                default:
                    throw Error.UnhandledBindingType(node.BindingType); 
            }
        } 
 
        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment node) {
            return node.Update(Visit(node.Expression)); 
        } 

        ///  
        /// Visits the children of the .
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node) { 
            return node.Update(Visit(node.Bindings, VisitMemberBinding)); 
        }
 
        /// 
        /// Visits the children of the .
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding node) { 
            return node.Update(Visit(node.Initializers, VisitElementInit));
        } 


        //
        // Prevent some common cases of invalid rewrites. 
        //
        // Essentially, we don't want the rewritten node to be semantically 
        // bound by the factory, which may do the wrong thing. Instead we 
        // require derived classes to be explicit about what they want to do if
        // types change. 
        //
        private static UnaryExpression ValidateUnary(UnaryExpression before, UnaryExpression after) {
            if (before != after && before.Method == null) {
                if (after.Method != null) { 
                    throw Error.MustRewriteWithoutMethod(after.Method, "VisitUnary");
                } 
 
                // rethrow has null operand
                if (before.Operand != null && after.Operand != null) { 
                    ValidateChildType(before.Operand.Type, after.Operand.Type, "VisitUnary");
                }
            }
            return after; 
        }
 
        private static BinaryExpression ValidateBinary(BinaryExpression before, BinaryExpression after) { 
            if (before != after && before.Method == null) {
                if (after.Method != null) { 
                    throw Error.MustRewriteWithoutMethod(after.Method, "VisitBinary");
                }

                ValidateChildType(before.Left.Type, after.Left.Type, "VisitBinary"); 
                ValidateChildType(before.Right.Type, after.Right.Type, "VisitBinary");
            } 
            return after; 
        }
 
        // We wouldn't need this if switch didn't infer the method.
        private static SwitchExpression ValidateSwitch(SwitchExpression before, SwitchExpression after) {
            // If we did not have a method, we don't want to bind to one,
            // it might not be the right thing. 
            if (before.Comparison == null && after.Comparison != null) {
                throw Error.MustRewriteWithoutMethod(after.Comparison, "VisitSwitch"); 
            } 
            return after;
        } 

        // Value types must stay as the same type, otherwise it's now a
        // different operation, e.g. adding two doubles vs adding two ints.
        private static void ValidateChildType(Type before, Type after, string methodName) { 
            if (before.IsValueType) {
                if (TypeUtils.AreEquivalent(before, after)) { 
                    // types are the same value type 
                    return;
                } 
            } else if (!after.IsValueType) {
                // both are reference types
                return;
            } 

            // Otherwise, it's an invalid type change. 
            throw Error.MustRewriteChildToSameType(before, after, methodName); 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
/* **************************************************************************** 
 *
 * Copyright (c) Microsoft Corporation.
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 * 
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/ 

using System.Collections.ObjectModel; 
using System.Diagnostics; 
using System.Dynamic.Utils;
using System.Runtime.CompilerServices; 

#if SILVERLIGHT
using System.Core;
#endif 

namespace System.Linq.Expressions { 
 
    /// 
    /// Represents a visitor or rewriter for expression trees. 
    /// 
    /// 
    /// This class is designed to be inherited to create more specialized
    /// classes whose functionality requires traversing, examining or copying 
    /// an expression tree.
    ///  
    public abstract class ExpressionVisitor { 

        ///  
        /// Initializes a new instance of .
        /// 
        protected ExpressionVisitor() {
        } 

        ///  
        /// Dispatches the expression to one of the more specialized visit methods in this class. 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        public virtual Expression Visit(Expression node) {
            if (node != null) { 
                return node.Accept(this);
            } 
            return null; 
        }
 
        /// 
        /// Dispatches the list of expressions to one of the more specialized visit methods in this class.
        /// 
        /// The expressions to visit. 
        /// The modified expression list, if any of the elements were modified;
        /// otherwise, returns the original expression list. 
        public ReadOnlyCollection Visit(ReadOnlyCollection nodes) { 
            Expression[] newNodes = null;
            for (int i = 0, n = nodes.Count; i < n; i++) { 
                Expression node = Visit(nodes[i]);

                if (newNodes != null) {
                    newNodes[i] = node; 
                } else if (!object.ReferenceEquals(node, nodes[i])) {
                    newNodes = new Expression[n]; 
                    for (int j = 0; j < i; j++) { 
                        newNodes[j] = nodes[j];
                    } 
                    newNodes[i] = node;
                }
            }
            if (newNodes == null) { 
                return nodes;
            } 
            return new TrueReadOnlyCollection(newNodes); 
        }
 
        internal Expression[] VisitArguments(IArgumentProvider nodes) {
            Expression[] newNodes = null;
            for (int i = 0, n = nodes.ArgumentCount; i < n; i++) {
                Expression curNode = nodes.GetArgument(i); 
                Expression node = Visit(curNode);
 
                if (newNodes != null) { 
                    newNodes[i] = node;
                } else if (!object.ReferenceEquals(node, curNode)) { 
                    newNodes = new Expression[n];
                    for (int j = 0; j < i; j++) {
                        newNodes[j] = nodes.GetArgument(j);
                    } 
                    newNodes[i] = node;
                } 
            } 
            return newNodes;
        } 

        /// 
        /// Visits all nodes in the collection using a specified element visitor.
        ///  
        /// The type of the nodes.
        /// The nodes to visit. 
        /// A delegate that visits a single element, 
        /// optionally replacing it with a new element.
        /// The modified node list, if any of the elements were modified; 
        /// otherwise, returns the original node list.
        public static ReadOnlyCollection Visit(ReadOnlyCollection nodes, Func elementVisitor) {
            T[] newNodes = null;
            for (int i = 0, n = nodes.Count; i < n; i++) { 
                T node = elementVisitor(nodes[i]);
                if (newNodes != null) { 
                    newNodes[i] = node; 
                } else if (!object.ReferenceEquals(node, nodes[i])) {
                    newNodes = new T[n]; 
                    for (int j = 0; j < i; j++) {
                        newNodes[j] = nodes[j];
                    }
                    newNodes[i] = node; 
                }
            } 
            if (newNodes == null) { 
                return nodes;
            } 
            return new TrueReadOnlyCollection(newNodes);
        }

        ///  
        /// Visits an expression, casting the result back to the original expression type.
        ///  
        /// The type of the expression. 
        /// The expression to visit.
        /// The name of the calling method; used to report to report a better error message. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        /// The visit method for this node returned a different type.
        public T VisitAndConvert(T node, string callerName) where T : Expression { 
            if (node == null) {
                return null; 
            } 
            node = Visit(node) as T;
            if (node == null) { 
                throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName);
            }
            return node;
        } 

        ///  
        /// Visits an expression, casting the result back to the original expression type. 
        /// 
        /// The type of the expression. 
        /// The expression to visit.
        /// The name of the calling method; used to report to report a better error message.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        /// The visit method for this node returned a different type.
        public ReadOnlyCollection VisitAndConvert(ReadOnlyCollection nodes, string callerName) where T : Expression { 
            T[] newNodes = null; 
            for (int i = 0, n = nodes.Count; i < n; i++) {
                T node = Visit(nodes[i]) as T; 
                if (node == null) {
                    throw Error.MustRewriteToSameNode(callerName, typeof(T), callerName);
                }
 
                if (newNodes != null) {
                    newNodes[i] = node; 
                } else if (!object.ReferenceEquals(node, nodes[i])) { 
                    newNodes = new T[n];
                    for (int j = 0; j < i; j++) { 
                        newNodes[j] = nodes[j];
                    }
                    newNodes[i] = node;
                } 
            }
            if (newNodes == null) { 
                return nodes; 
            }
            return new TrueReadOnlyCollection(newNodes); 
        }

        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitBinary(BinaryExpression node) { 
            // Walk children in evaluation order: left, conversion, right
            return ValidateBinary(
                node,
                node.Update( 
                    Visit(node.Left),
                    VisitAndConvert(node.Conversion, "VisitBinary"), 
                    Visit(node.Right) 
                )
            ); 
        }

        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitBlock(BlockExpression node) { 
            int count = node.ExpressionCount;
            Expression[] nodes = null;
            for (int i = 0; i < count; i++) {
                Expression oldNode = node.GetExpression(i); 
                Expression newNode = Visit(oldNode);
 
                if (oldNode != newNode) { 
                    if (nodes == null) {
                        nodes = new Expression[count]; 
                    }
                    nodes[i] = newNode;
                }
            } 
            var v = VisitAndConvert(node.Variables, "VisitBlock");
 
            if (v == node.Variables && nodes == null) { 
                return node;
            } else { 
                for (int i = 0; i < count; i++) {
                    if (nodes[i] == null) {
                        nodes[i] = node.GetExpression(i);
                    } 
                }
            } 
 
            return node.Rewrite(v, nodes);
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitConditional(ConditionalExpression node) {
            return node.Update(Visit(node.Test), Visit(node.IfTrue), Visit(node.IfFalse)); 
        }

        /// 
        /// Visits the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitConstant(ConstantExpression node) { 
            return node;
        }

        ///  
        /// Visits the .
        ///  
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitDebugInfo(DebugInfoExpression node) {
            return node;
        }
 
        /// 
        /// Visits the children of the . 
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitDynamic(DynamicExpression node) {
            Expression[] a = VisitArguments((IArgumentProvider)node);
            if (a == null) { 
                return node;
            } 
 
            return node.Rewrite(a);
        } 

        /// 
        /// Visits the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitDefault(DefaultExpression node) {
            return node; 
        }

        /// 
        /// Visits the children of the extension expression. 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        ///  
        /// This can be overridden to visit or rewrite specific extension nodes.
        /// If it is not overridden, this method will call ,
        /// which gives the node a chance to walk its children. By default,
        ///  will try to reduce the node. 
        /// 
        protected internal virtual Expression VisitExtension(Expression node) { 
            return node.VisitChildren(this); 
        }
 
        /// 
        /// Visits the children of the .
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitGoto(GotoExpression node) { 
            return node.Update(VisitLabelTarget(node.Target), Visit(node.Value));
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitInvocation(InvocationExpression node) {
            Expression e = Visit(node.Expression); 
            Expression[] a = VisitArguments(node);
            if (e == node.Expression && a == null) {
                return node;
            } 

            return node.Rewrite(e, a); 
        } 

        ///  
        /// Visits the .
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected virtual LabelTarget VisitLabelTarget(LabelTarget node) { 
            return node; 
        }
 
        /// 
        /// Visits the children of the .
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitLabel(LabelExpression node) { 
            return node.Update(VisitLabelTarget(node.Target), Visit(node.DefaultValue));
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The type of the delegate.
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitLambda(Expression node) { 
            return node.Update(Visit(node.Body), VisitAndConvert(node.Parameters, "VisitLambda"));
        }

        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitLoop(LoopExpression node) {
            return node.Update(VisitLabelTarget(node.BreakLabel), VisitLabelTarget(node.ContinueLabel), Visit(node.Body));
        }
 
        /// 
        /// Visits the children of the . 
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitMember(MemberExpression node) {
            return node.Update(Visit(node.Expression));
        } 

        ///  
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitIndex(IndexExpression node) {
            Expression o = Visit(node.Object); 
            Expression[] a = VisitArguments(node);
            if (o == node.Object && a == null) { 
                return node; 
            }
 
            return node.Rewrite(o, a);
        }

        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitMethodCall(MethodCallExpression node) {
            Expression o = Visit(node.Object);
            Expression[] a = VisitArguments((IArgumentProvider)node);
            if (o == node.Object && a == null) { 
                return node;
            } 
 
            return node.Rewrite(o, a);
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitNewArray(NewArrayExpression node) {
            return node.Update(Visit(node.Expressions)); 
        }

        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] 
        protected internal virtual Expression VisitNew(NewExpression node) {
            return node.Update(Visit(node.Arguments));
        }
 
        /// 
        /// Visits the . 
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitParameter(ParameterExpression node) {
            return node;
        } 

        ///  
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitRuntimeVariables(RuntimeVariablesExpression node) {
            return node.Update(VisitAndConvert(node.Variables, "VisitRuntimeVariables")); 
        }
 
        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected virtual SwitchCase VisitSwitchCase(SwitchCase node) { 
            return node.Update(Visit(node.TestValues), Visit(node.Body));
        } 
 
        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitSwitch(SwitchExpression node) {
            return ValidateSwitch( 
                node, 
                node.Update(
                    Visit(node.SwitchValue), 
                    Visit(node.Cases, VisitSwitchCase),
                    Visit(node.DefaultBody)
                )
            ); 
        }
 
        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected virtual CatchBlock VisitCatchBlock(CatchBlock node) { 
            return node.Update(VisitAndConvert(node.Variable, "VisitCatchBlock"), Visit(node.Filter), Visit(node.Body));
        } 
 
        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitTry(TryExpression node) {
            return node.Update( 
                Visit(node.Body), 
                Visit(node.Handlers, VisitCatchBlock),
                Visit(node.Finally), 
                Visit(node.Fault)
            );
        }
 
        /// 
        /// Visits the children of the . 
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitTypeBinary(TypeBinaryExpression node) {
            return node.Update(Visit(node.Expression));
        } 

        ///  
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitUnary(UnaryExpression node) {
            return ValidateUnary(node, node.Update(Visit(node.Operand))); 
        }
 
        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected internal virtual Expression VisitMemberInit(MemberInitExpression node) { 
            return node.Update(
                VisitAndConvert(node.NewExpression, "VisitMemberInit"), 
                Visit(node.Bindings, VisitMemberBinding) 
            );
        } 

        /// 
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression. 
        protected internal virtual Expression VisitListInit(ListInitExpression node) {
            return node.Update( 
                VisitAndConvert(node.NewExpression, "VisitListInit"),
                Visit(node.Initializers, VisitElementInit)
            );
        } 

        ///  
        /// Visits the children of the . 
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected virtual ElementInit VisitElementInit(ElementInit node) {
            return node.Update(Visit(node.Arguments)); 
        }
 
        ///  
        /// Visits the children of the .
        ///  
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression.
        protected virtual MemberBinding VisitMemberBinding(MemberBinding node) { 
            switch (node.BindingType) {
                case MemberBindingType.Assignment: 
                    return VisitMemberAssignment((MemberAssignment)node); 
                case MemberBindingType.MemberBinding:
                    return VisitMemberMemberBinding((MemberMemberBinding)node); 
                case MemberBindingType.ListBinding:
                    return VisitMemberListBinding((MemberListBinding)node);
                default:
                    throw Error.UnhandledBindingType(node.BindingType); 
            }
        } 
 
        /// 
        /// Visits the children of the . 
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment node) {
            return node.Update(Visit(node.Expression)); 
        } 

        ///  
        /// Visits the children of the .
        /// 
        /// The expression to visit.
        /// The modified expression, if it or any subexpression was modified; 
        /// otherwise, returns the original expression.
        protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node) { 
            return node.Update(Visit(node.Bindings, VisitMemberBinding)); 
        }
 
        /// 
        /// Visits the children of the .
        /// 
        /// The expression to visit. 
        /// The modified expression, if it or any subexpression was modified;
        /// otherwise, returns the original expression. 
        protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding node) { 
            return node.Update(Visit(node.Initializers, VisitElementInit));
        } 


        //
        // Prevent some common cases of invalid rewrites. 
        //
        // Essentially, we don't want the rewritten node to be semantically 
        // bound by the factory, which may do the wrong thing. Instead we 
        // require derived classes to be explicit about what they want to do if
        // types change. 
        //
        private static UnaryExpression ValidateUnary(UnaryExpression before, UnaryExpression after) {
            if (before != after && before.Method == null) {
                if (after.Method != null) { 
                    throw Error.MustRewriteWithoutMethod(after.Method, "VisitUnary");
                } 
 
                // rethrow has null operand
                if (before.Operand != null && after.Operand != null) { 
                    ValidateChildType(before.Operand.Type, after.Operand.Type, "VisitUnary");
                }
            }
            return after; 
        }
 
        private static BinaryExpression ValidateBinary(BinaryExpression before, BinaryExpression after) { 
            if (before != after && before.Method == null) {
                if (after.Method != null) { 
                    throw Error.MustRewriteWithoutMethod(after.Method, "VisitBinary");
                }

                ValidateChildType(before.Left.Type, after.Left.Type, "VisitBinary"); 
                ValidateChildType(before.Right.Type, after.Right.Type, "VisitBinary");
            } 
            return after; 
        }
 
        // We wouldn't need this if switch didn't infer the method.
        private static SwitchExpression ValidateSwitch(SwitchExpression before, SwitchExpression after) {
            // If we did not have a method, we don't want to bind to one,
            // it might not be the right thing. 
            if (before.Comparison == null && after.Comparison != null) {
                throw Error.MustRewriteWithoutMethod(after.Comparison, "VisitSwitch"); 
            } 
            return after;
        } 

        // Value types must stay as the same type, otherwise it's now a
        // different operation, e.g. adding two doubles vs adding two ints.
        private static void ValidateChildType(Type before, Type after, string methodName) { 
            if (before.IsValueType) {
                if (TypeUtils.AreEquivalent(before, after)) { 
                    // types are the same value type 
                    return;
                } 
            } else if (!after.IsValueType) {
                // both are reference types
                return;
            } 

            // Otherwise, it's an invalid type change. 
            throw Error.MustRewriteChildToSameType(before, after, methodName); 
        }
    } 
}

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