Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / ALinq / InputBinder.cs / 1305376 / 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 { #region Namespaces. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq.Expressions; using System.Reflection; #endregion Namespaces. ////// 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 : DataServiceALinqExpressionVisitor { #region Private fields. ///Tracks which resource sets are referenced by the argument expression private readonly HashSetreferencedInputs = 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; #endregion Private fields. ////// 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 /// The expression 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 ///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 rebound version of internal static Expression Bind(Expression e, ResourceExpression currentInput, ParameterExpression inputParameter, Listwhere MemberExpression/ParameterExpressions that /// represent resource set references have been replaced with appropriate InputReferenceExpressions. /// 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); Expression result = binder.Visit(e); referencedInputs.AddRange(binder.referencedInputs); return result; } /// /// 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; StacknestedAccesses = new Stack (); MemberExpression memberRef = m; while (memberRef != null && memberRef.Member.MemberType == MemberTypes.Property && memberRef.Expression != null) { nestedAccesses.Push((PropertyInfo)memberRef.Member); if (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) { return m; } ResourceExpression target = this.input; ResourceSetExpression targetSet = this.inputSet; bool transparentScopeTraversed = false; // Process all the traversals through transparent scopes. while (nestedAccesses.Count > 0) { if (targetSet == null || !targetSet.HasTransparentScope) { break; } // Peek the property; pop it once it's consumed // (it could be a non-transparent-identifier access). PropertyInfo currentProp = nestedAccesses.Peek(); // If this is the accessor for the target, then the member // refers to the target itself. if (currentProp.Name.Equals(targetSet.TransparentScope.Accessor, StringComparison.Ordinal)) { target = targetSet; nestedAccesses.Pop(); transparentScopeTraversed = true; continue; } // This member could also be one of the in-scope sources of the target. Expression source; if (!targetSet.TransparentScope.SourceAccessors.TryGetValue(currentProp.Name, out source)) { break; } transparentScopeTraversed = true; nestedAccesses.Pop(); Debug.Assert(source != null, "source != null -- otherwise ResourceBinder created an accessor to nowhere"); InputReferenceExpression sourceReference = source as InputReferenceExpression; if (sourceReference == null) { targetSet = source as ResourceSetExpression; if (targetSet == null || !targetSet.HasTransparentScope) { target = (ResourceExpression)source; } } else { targetSet = sourceReference.Target as ResourceSetExpression; target = targetSet; } } // If no traversals were made, the original expression is OK. if (!transparentScopeTraversed) { return m; } // Process traversals after the transparent scope. Expression result = this.CreateReference(target); while (nestedAccesses.Count > 0) { result = Expression.Property(result, nestedAccesses.Pop()); } return result; } /// /// 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 /// The resource(set) for which a reference was found ///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. /// 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 { #region Namespaces. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq.Expressions; using System.Reflection; #endregion Namespaces. ////// 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 : DataServiceALinqExpressionVisitor { #region Private fields. ///Tracks which resource sets are referenced by the argument expression private readonly HashSetreferencedInputs = 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; #endregion Private fields. ////// 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 /// The expression 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 ///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 rebound version of internal static Expression Bind(Expression e, ResourceExpression currentInput, ParameterExpression inputParameter, Listwhere MemberExpression/ParameterExpressions that /// represent resource set references have been replaced with appropriate InputReferenceExpressions. /// 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); Expression result = binder.Visit(e); referencedInputs.AddRange(binder.referencedInputs); return result; } /// /// 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; StacknestedAccesses = new Stack (); MemberExpression memberRef = m; while (memberRef != null && memberRef.Member.MemberType == MemberTypes.Property && memberRef.Expression != null) { nestedAccesses.Push((PropertyInfo)memberRef.Member); if (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) { return m; } ResourceExpression target = this.input; ResourceSetExpression targetSet = this.inputSet; bool transparentScopeTraversed = false; // Process all the traversals through transparent scopes. while (nestedAccesses.Count > 0) { if (targetSet == null || !targetSet.HasTransparentScope) { break; } // Peek the property; pop it once it's consumed // (it could be a non-transparent-identifier access). PropertyInfo currentProp = nestedAccesses.Peek(); // If this is the accessor for the target, then the member // refers to the target itself. if (currentProp.Name.Equals(targetSet.TransparentScope.Accessor, StringComparison.Ordinal)) { target = targetSet; nestedAccesses.Pop(); transparentScopeTraversed = true; continue; } // This member could also be one of the in-scope sources of the target. Expression source; if (!targetSet.TransparentScope.SourceAccessors.TryGetValue(currentProp.Name, out source)) { break; } transparentScopeTraversed = true; nestedAccesses.Pop(); Debug.Assert(source != null, "source != null -- otherwise ResourceBinder created an accessor to nowhere"); InputReferenceExpression sourceReference = source as InputReferenceExpression; if (sourceReference == null) { targetSet = source as ResourceSetExpression; if (targetSet == null || !targetSet.HasTransparentScope) { target = (ResourceExpression)source; } } else { targetSet = sourceReference.Target as ResourceSetExpression; target = targetSet; } } // If no traversals were made, the original expression is OK. if (!transparentScopeTraversed) { return m; } // Process traversals after the transparent scope. Expression result = this.CreateReference(target); while (nestedAccesses.Count > 0) { result = Expression.Property(result, nestedAccesses.Pop()); } return result; } /// /// 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 /// The resource(set) for which a reference was found ///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. /// 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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- KnownIds.cs
- PageParser.cs
- OleDragDropHandler.cs
- TypeConverterBase.cs
- AnnotationAuthorChangedEventArgs.cs
- CodeExpressionStatement.cs
- KeyPressEvent.cs
- StoragePropertyMapping.cs
- Geometry3D.cs
- PageContentAsyncResult.cs
- TemplateEditingService.cs
- Point3DValueSerializer.cs
- BinaryCommonClasses.cs
- ScrollViewerAutomationPeer.cs
- RegexCompiler.cs
- VScrollProperties.cs
- StyleCollectionEditor.cs
- LowerCaseStringConverter.cs
- SharedStatics.cs
- HuffCodec.cs
- XmlSchemaAppInfo.cs
- ICspAsymmetricAlgorithm.cs
- FontConverter.cs
- WebPartUtil.cs
- ValidatingReaderNodeData.cs
- EpmCustomContentWriterNodeData.cs
- CancelEventArgs.cs
- BindableTemplateBuilder.cs
- CodeSubDirectory.cs
- WorkflowRuntimeServiceElement.cs
- DefaultBindingPropertyAttribute.cs
- Queue.cs
- CharEnumerator.cs
- SqlCharStream.cs
- SHA512.cs
- PropertyGeneratedEventArgs.cs
- HtmlButton.cs
- LinkedResource.cs
- HMAC.cs
- StdRegProviderWrapper.cs
- ProcessInfo.cs
- HashJoinQueryOperatorEnumerator.cs
- OLEDB_Enum.cs
- GatewayIPAddressInformationCollection.cs
- KnownBoxes.cs
- BamlReader.cs
- ActivationArguments.cs
- XPathDescendantIterator.cs
- FrameworkContentElement.cs
- EllipticalNodeOperations.cs
- ScrollProperties.cs
- NameValueConfigurationCollection.cs
- ThreadStartException.cs
- XmlnsCache.cs
- SimpleHandlerBuildProvider.cs
- FontUnitConverter.cs
- XamlPathDataSerializer.cs
- UntypedNullExpression.cs
- VisualTreeUtils.cs
- safelink.cs
- WebPartConnectVerb.cs
- PassportAuthenticationModule.cs
- DynamicValueConverter.cs
- ToolStripDropDownClosedEventArgs.cs
- x509store.cs
- ZipIOExtraFieldElement.cs
- SmtpCommands.cs
- XmlConvert.cs
- DropTarget.cs
- IgnoreDeviceFilterElement.cs
- MenuAdapter.cs
- ConfigUtil.cs
- Utils.cs
- FocusWithinProperty.cs
- SizeAnimationBase.cs
- NavigationWindowAutomationPeer.cs
- TreeViewImageIndexConverter.cs
- OleDbDataReader.cs
- BufferedStream2.cs
- LightweightCodeGenerator.cs
- HandledMouseEvent.cs
- TemplateBaseAction.cs
- ThreadAttributes.cs
- SettingsSection.cs
- DefaultExpression.cs
- Deflater.cs
- WebPartTransformer.cs
- EventOpcode.cs
- XmlAtomErrorReader.cs
- OrderByExpression.cs
- HeaderUtility.cs
- DataGridColumnReorderingEventArgs.cs
- EventItfInfo.cs
- ToolBarButton.cs
- DirectoryGroupQuery.cs
- ParseHttpDate.cs
- DesignerCommandSet.cs
- Selection.cs
- VerticalAlignConverter.cs
- DoubleUtil.cs