Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Authorization.cs
- WindowsNonControl.cs
- ScriptHandlerFactory.cs
- ValuePattern.cs
- AutomationProperties.cs
- ConvertEvent.cs
- DurableInstanceProvider.cs
- BufferedResponseStream.cs
- PlacementWorkspace.cs
- MailMessageEventArgs.cs
- ServiceOperation.cs
- DoWhile.cs
- WebPartsPersonalization.cs
- LoadRetryConstantStrategy.cs
- Storyboard.cs
- Scene3D.cs
- CatalogUtil.cs
- AuthenticationManager.cs
- ThreadBehavior.cs
- MenuTracker.cs
- TraceLog.cs
- SqlStatistics.cs
- UserControlAutomationPeer.cs
- ErrorEventArgs.cs
- KeyedHashAlgorithm.cs
- EntityParameterCollection.cs
- HandleCollector.cs
- RijndaelCryptoServiceProvider.cs
- HelpHtmlBuilder.cs
- BaseCAMarshaler.cs
- SmiEventSink.cs
- OdbcErrorCollection.cs
- ColorPalette.cs
- BitmapEffectDrawing.cs
- HtmlInputCheckBox.cs
- Ops.cs
- SHA1CryptoServiceProvider.cs
- EncryptedKeyHashIdentifierClause.cs
- SubstitutionResponseElement.cs
- SessionState.cs
- StylusEventArgs.cs
- Camera.cs
- ProfileService.cs
- CompoundFileIOPermission.cs
- PackWebRequest.cs
- XmlSchemaParticle.cs
- Parser.cs
- WindowInteractionStateTracker.cs
- InvalidPrinterException.cs
- QilPatternVisitor.cs
- HTTPNotFoundHandler.cs
- HtmlMeta.cs
- HttpConfigurationContext.cs
- Model3DGroup.cs
- Point3DAnimation.cs
- Group.cs
- MaskDesignerDialog.cs
- FacetEnabledSchemaElement.cs
- CollectionType.cs
- HebrewCalendar.cs
- GZipObjectSerializer.cs
- OutOfProcStateClientManager.cs
- OrderByLifter.cs
- InternalPolicyElement.cs
- ConfigurationCollectionAttribute.cs
- SecurityCookieModeValidator.cs
- ProxyGenerationError.cs
- ToolBarTray.cs
- DependencyObjectType.cs
- ButtonField.cs
- Visual3DCollection.cs
- AuthStoreRoleProvider.cs
- CompilationSection.cs
- DataServiceSaveChangesEventArgs.cs
- LinkDescriptor.cs
- CalendarDateRangeChangingEventArgs.cs
- XPathItem.cs
- ValidationContext.cs
- SqlRowUpdatingEvent.cs
- RequestQueryParser.cs
- UpdateTracker.cs
- TimelineGroup.cs
- MenuItemBinding.cs
- SecurityUtils.cs
- BinaryFormatter.cs
- DNS.cs
- InputReport.cs
- ReflectTypeDescriptionProvider.cs
- DataObject.cs
- DirectoryNotFoundException.cs
- DataGridToolTip.cs
- base64Transforms.cs
- ScriptReferenceBase.cs
- UInt32Storage.cs
- ColorContext.cs
- Rect3D.cs
- SmiConnection.cs
- ImageCollectionEditor.cs
- AssemblyNameEqualityComparer.cs
- AccessDataSourceView.cs