Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Objects / ELinq / ClosureBinding.cs / 2 / ClosureBinding.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] //--------------------------------------------------------------------- using System.Collections; using LinqExpression = System.Linq.Expressions.Expression; using CqtExpression = System.Data.Common.CommandTrees.DbExpression; using System.Diagnostics; using System.Collections.Generic; using System.Linq.Expressions; using System.Data.Common.Utils; using System.Data.Common.CommandTrees; using System.Globalization; using System.Data.Metadata.Edm; using System.Reflection; using System.Linq; using System.Threading; namespace System.Data.Objects.ELinq { ////// Binding between an object parameter or sub-query and LINQ expression that needs to be /// re-evaluated before executing a query because it is part of the closure. /// /// Invariants: the binding defines either the Parameter or the Query property, not both. /// internal abstract class ClosureBinding { #region Constructors private ClosureBinding(LinqExpression sourceExpression) { _sourceExpression = sourceExpression; } #endregion #region Fields private readonly LinqExpression _sourceExpression; private static readonly string s_parameterPrefix = "p__linq__"; private static long s_parameterNumber; #endregion #region Properties ////// Gets the query produced by this closure expression. Returns null if no /// query is produced. /// internal abstract ObjectQuery Query { get; } ////// Gets the expression produced by this closure expression. Returns null if no /// expression is produced. /// internal abstract LinqExpression Expression { get; } ////// Gets the parameter storing the primitive value produced by this closure expression. /// Returns null if no primitive value is produced. /// internal abstract ObjectParameter Parameter { get; } #endregion #region Methods ////// Evaluates the binding and populates the object parameter value. /// ///true if the entire expression should be re-evaluated (if a sub-expression has changed); /// false otherwise internal abstract bool EvaluateBinding(); internal abstract ClosureBinding CopyToContext(ExpressionConverter context); internal static bool TryGetTypeUsageForObjectParameter(ObjectParameter parameter, ClrPerspective perspective, out TypeUsage typeUsage) { // since ObjectParameters do not allow users to especify 'facets', make // sure that the parameter typeusage is not populated with the provider // dafault facet values if (perspective.TryGetTypeByName(parameter.MappableType.FullName, false, // bIgnoreCase out typeUsage) && TypeSemantics.IsPrimitiveType(typeUsage)) { return true; } typeUsage = null; return false; } ////// requires: expression must not be null /// Attempt to treat the given expression as a supported parameter reference in a closure. /// Succeeds if the pattern of the expression is precisely Member(Constant), and the member /// is of primitive type. /// /// Expression to check. /// Perspective to use to resolve expression type. /// Determines whether Lambda sub-expressions are permitted in this context. /// Closure binding corresponding to the given expression. /// Type usage for the binding. ///true if the given expression can be bound internal static bool TryCreateClosureBinding(LinqExpression expression, ClrPerspective perspective, bool allowLambda, HashSetclosureCandidates, out ClosureBinding binding, out TypeUsage typeUsage) { Debug.Assert(null != expression); if (ExpressionEvaluator.IsExpressionNodeAClosure(expression) && closureCandidates.Contains(expression)) // all nodes below it must qualify also { ObjectParameter parameter = new ObjectParameter(GenerateParameterName(), expression.Type); if(TryGetTypeUsageForObjectParameter(parameter, perspective, out typeUsage)) { binding = new ParameterBinding(expression, parameter); // compute the parameter value during translation since we translate directly // before evaluating (in other words, the value of the parameter will not change // between now and the time results are produced) binding.EvaluateBinding(); return true; } // determine if the expression yields an inline ObjectQuery or Expression object result = ExpressionEvaluator.EvaluateExpression(expression); ObjectQuery resultQuery = result as ObjectQuery; if (resultQuery != null) { binding = new NestedLogicBinding(expression, result, resultQuery.QueryState.UserSpecifiedMergeOption); return true; } else if (allowLambda && result is LambdaExpression) { binding = new NestedLogicBinding(expression, result, null); return true; } } // doesn't match the pattern binding = null; typeUsage = null; return false; } internal static string GenerateParameterName() { // To avoid collisions with user parameters (the full set is not // known at this time) we plug together an 'unlikely' prefix and // a number. return String.Format(CultureInfo.InvariantCulture, "{0}{1}", s_parameterPrefix, Interlocked.Increment(ref s_parameterNumber)); } #endregion #region Nested types private class NestedLogicBinding : ClosureBinding { private MergeOption? _mergeOption; internal NestedLogicBinding(LinqExpression sourceExpression, object nestedLogic, MergeOption? mergeOption) : base(sourceExpression) { _nestedLogic = nestedLogic; _mergeOption = mergeOption; } private object _nestedLogic; internal override ClosureBinding CopyToContext(ExpressionConverter context) { return this; } internal override bool EvaluateBinding() { // must recompile entire expression if the sub-expression has changed object currentLogic = ExpressionEvaluator.EvaluateExpression(_sourceExpression); if (object.ReferenceEquals(_nestedLogic, currentLogic)) { // The instances are the same; however, if the nested logic is actually // an instance of ObjectQuery, then any mutable properties on the instance // may also have changed. Currently only MergeOption is significant, so it // must be compared here. ObjectQuery query = currentLogic as ObjectQuery; if (query == null) { // The nested logic is not an ObjectQuery; simply return false. return false; } // The only way the merge option can change in a way that affects us // here is if it has been explicitly set using ObjectQuery.MergeOption. MergeOption? newMergeOption = query.QueryState.UserSpecifiedMergeOption; if (!newMergeOption.HasValue && !_mergeOption.HasValue) { // No difference. return false; } if (newMergeOption.HasValue && _mergeOption.HasValue && newMergeOption.Value == _mergeOption.Value) { // No difference. return false; } } return true; } internal override LinqExpression Expression { get { return _nestedLogic as LinqExpression; } } internal override ObjectQuery Query { get { return _nestedLogic as ObjectQuery; } } internal override ObjectParameter Parameter { get { return null; } } } private class ParameterBinding : ClosureBinding { internal ParameterBinding(LinqExpression sourceExpression, ObjectParameter parameter) : base(sourceExpression) { _parameter = parameter; } private ObjectParameter _parameter; internal override ClosureBinding CopyToContext(ExpressionConverter context) { ObjectParameter targetParameter = null; if (context.Parameters != null) { targetParameter = context.Parameters[_parameter.Name]; } return new ParameterBinding(_sourceExpression, targetParameter); } internal override bool EvaluateBinding() { object currentValue = ExpressionEvaluator.EvaluateExpression(_sourceExpression); _parameter.Value = currentValue; return false; } internal override LinqExpression Expression { get { return null; } } internal override ObjectQuery Query { get { return null; } } internal override ObjectParameter Parameter { get { return _parameter; } } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] //--------------------------------------------------------------------- using System.Collections; using LinqExpression = System.Linq.Expressions.Expression; using CqtExpression = System.Data.Common.CommandTrees.DbExpression; using System.Diagnostics; using System.Collections.Generic; using System.Linq.Expressions; using System.Data.Common.Utils; using System.Data.Common.CommandTrees; using System.Globalization; using System.Data.Metadata.Edm; using System.Reflection; using System.Linq; using System.Threading; namespace System.Data.Objects.ELinq { ////// Binding between an object parameter or sub-query and LINQ expression that needs to be /// re-evaluated before executing a query because it is part of the closure. /// /// Invariants: the binding defines either the Parameter or the Query property, not both. /// internal abstract class ClosureBinding { #region Constructors private ClosureBinding(LinqExpression sourceExpression) { _sourceExpression = sourceExpression; } #endregion #region Fields private readonly LinqExpression _sourceExpression; private static readonly string s_parameterPrefix = "p__linq__"; private static long s_parameterNumber; #endregion #region Properties ////// Gets the query produced by this closure expression. Returns null if no /// query is produced. /// internal abstract ObjectQuery Query { get; } ////// Gets the expression produced by this closure expression. Returns null if no /// expression is produced. /// internal abstract LinqExpression Expression { get; } ////// Gets the parameter storing the primitive value produced by this closure expression. /// Returns null if no primitive value is produced. /// internal abstract ObjectParameter Parameter { get; } #endregion #region Methods ////// Evaluates the binding and populates the object parameter value. /// ///true if the entire expression should be re-evaluated (if a sub-expression has changed); /// false otherwise internal abstract bool EvaluateBinding(); internal abstract ClosureBinding CopyToContext(ExpressionConverter context); internal static bool TryGetTypeUsageForObjectParameter(ObjectParameter parameter, ClrPerspective perspective, out TypeUsage typeUsage) { // since ObjectParameters do not allow users to especify 'facets', make // sure that the parameter typeusage is not populated with the provider // dafault facet values if (perspective.TryGetTypeByName(parameter.MappableType.FullName, false, // bIgnoreCase out typeUsage) && TypeSemantics.IsPrimitiveType(typeUsage)) { return true; } typeUsage = null; return false; } ////// requires: expression must not be null /// Attempt to treat the given expression as a supported parameter reference in a closure. /// Succeeds if the pattern of the expression is precisely Member(Constant), and the member /// is of primitive type. /// /// Expression to check. /// Perspective to use to resolve expression type. /// Determines whether Lambda sub-expressions are permitted in this context. /// Closure binding corresponding to the given expression. /// Type usage for the binding. ///true if the given expression can be bound internal static bool TryCreateClosureBinding(LinqExpression expression, ClrPerspective perspective, bool allowLambda, HashSetclosureCandidates, out ClosureBinding binding, out TypeUsage typeUsage) { Debug.Assert(null != expression); if (ExpressionEvaluator.IsExpressionNodeAClosure(expression) && closureCandidates.Contains(expression)) // all nodes below it must qualify also { ObjectParameter parameter = new ObjectParameter(GenerateParameterName(), expression.Type); if(TryGetTypeUsageForObjectParameter(parameter, perspective, out typeUsage)) { binding = new ParameterBinding(expression, parameter); // compute the parameter value during translation since we translate directly // before evaluating (in other words, the value of the parameter will not change // between now and the time results are produced) binding.EvaluateBinding(); return true; } // determine if the expression yields an inline ObjectQuery or Expression object result = ExpressionEvaluator.EvaluateExpression(expression); ObjectQuery resultQuery = result as ObjectQuery; if (resultQuery != null) { binding = new NestedLogicBinding(expression, result, resultQuery.QueryState.UserSpecifiedMergeOption); return true; } else if (allowLambda && result is LambdaExpression) { binding = new NestedLogicBinding(expression, result, null); return true; } } // doesn't match the pattern binding = null; typeUsage = null; return false; } internal static string GenerateParameterName() { // To avoid collisions with user parameters (the full set is not // known at this time) we plug together an 'unlikely' prefix and // a number. return String.Format(CultureInfo.InvariantCulture, "{0}{1}", s_parameterPrefix, Interlocked.Increment(ref s_parameterNumber)); } #endregion #region Nested types private class NestedLogicBinding : ClosureBinding { private MergeOption? _mergeOption; internal NestedLogicBinding(LinqExpression sourceExpression, object nestedLogic, MergeOption? mergeOption) : base(sourceExpression) { _nestedLogic = nestedLogic; _mergeOption = mergeOption; } private object _nestedLogic; internal override ClosureBinding CopyToContext(ExpressionConverter context) { return this; } internal override bool EvaluateBinding() { // must recompile entire expression if the sub-expression has changed object currentLogic = ExpressionEvaluator.EvaluateExpression(_sourceExpression); if (object.ReferenceEquals(_nestedLogic, currentLogic)) { // The instances are the same; however, if the nested logic is actually // an instance of ObjectQuery, then any mutable properties on the instance // may also have changed. Currently only MergeOption is significant, so it // must be compared here. ObjectQuery query = currentLogic as ObjectQuery; if (query == null) { // The nested logic is not an ObjectQuery; simply return false. return false; } // The only way the merge option can change in a way that affects us // here is if it has been explicitly set using ObjectQuery.MergeOption. MergeOption? newMergeOption = query.QueryState.UserSpecifiedMergeOption; if (!newMergeOption.HasValue && !_mergeOption.HasValue) { // No difference. return false; } if (newMergeOption.HasValue && _mergeOption.HasValue && newMergeOption.Value == _mergeOption.Value) { // No difference. return false; } } return true; } internal override LinqExpression Expression { get { return _nestedLogic as LinqExpression; } } internal override ObjectQuery Query { get { return _nestedLogic as ObjectQuery; } } internal override ObjectParameter Parameter { get { return null; } } } private class ParameterBinding : ClosureBinding { internal ParameterBinding(LinqExpression sourceExpression, ObjectParameter parameter) : base(sourceExpression) { _parameter = parameter; } private ObjectParameter _parameter; internal override ClosureBinding CopyToContext(ExpressionConverter context) { ObjectParameter targetParameter = null; if (context.Parameters != null) { targetParameter = context.Parameters[_parameter.Name]; } return new ParameterBinding(_sourceExpression, targetParameter); } internal override bool EvaluateBinding() { object currentValue = ExpressionEvaluator.EvaluateExpression(_sourceExpression); _parameter.Value = currentValue; return false; } internal override LinqExpression Expression { get { return null; } } internal override ObjectQuery Query { get { return null; } } internal override ObjectParameter Parameter { get { return _parameter; } } } #endregion } } // 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
- TextRangeEditTables.cs
- Codec.cs
- CustomValidator.cs
- ActivityDelegate.cs
- BaseUriWithWildcard.cs
- DesignColumn.cs
- Section.cs
- ConstructorNeedsTagAttribute.cs
- WindowsUpDown.cs
- ObjectAnimationUsingKeyFrames.cs
- MetadataArtifactLoader.cs
- CommonRemoteMemoryBlock.cs
- StylusLogic.cs
- WindowsRichEditRange.cs
- DesignerActionPanel.cs
- UnknownWrapper.cs
- XmlSerializerAssemblyAttribute.cs
- PageCatalogPart.cs
- WebPermission.cs
- StaticResourceExtension.cs
- RowUpdatedEventArgs.cs
- XmlReflectionMember.cs
- ScrollChangedEventArgs.cs
- BrowserTree.cs
- Int32RectConverter.cs
- unsafeIndexingFilterStream.cs
- HitTestWithGeometryDrawingContextWalker.cs
- AspNetPartialTrustHelpers.cs
- UnitySerializationHolder.cs
- documentsequencetextcontainer.cs
- CorrelationQueryBehavior.cs
- MediaElementAutomationPeer.cs
- InputGestureCollection.cs
- SharedStream.cs
- WindowsGraphics2.cs
- HtmlTernaryTree.cs
- PropertyConverter.cs
- DataGridViewColumnCollectionDialog.cs
- HttpListenerPrefixCollection.cs
- DocobjHost.cs
- ButtonField.cs
- AccessibilityHelperForVista.cs
- CriticalFinalizerObject.cs
- TokenDescriptor.cs
- DropTarget.cs
- _SingleItemRequestCache.cs
- ColorConverter.cs
- AssemblyNameProxy.cs
- DesignerActionKeyboardBehavior.cs
- XPathNodePointer.cs
- AccessedThroughPropertyAttribute.cs
- DataRowExtensions.cs
- TreeIterator.cs
- EntityDataSourceState.cs
- ErrorWebPart.cs
- DataControlFieldCell.cs
- dtdvalidator.cs
- WebPartActionVerb.cs
- LogWriteRestartAreaAsyncResult.cs
- ZipFileInfoCollection.cs
- UnmanagedMarshal.cs
- CodePageUtils.cs
- WebPartMinimizeVerb.cs
- CalendarButtonAutomationPeer.cs
- Authorization.cs
- ScriptingSectionGroup.cs
- TemplatePropertyEntry.cs
- ColumnMap.cs
- ActivationServices.cs
- Knowncolors.cs
- MultiSelectRootGridEntry.cs
- PrincipalPermissionMode.cs
- FilteredAttributeCollection.cs
- SliderAutomationPeer.cs
- AssemblyHelper.cs
- CompilerInfo.cs
- RadioButtonPopupAdapter.cs
- AnimatedTypeHelpers.cs
- SqlRewriteScalarSubqueries.cs
- HttpValueCollection.cs
- NoResizeSelectionBorderGlyph.cs
- FileDialog.cs
- RegistryDataKey.cs
- ReaderOutput.cs
- ToolStripPanelRenderEventArgs.cs
- TableItemPattern.cs
- TextServicesContext.cs
- BoundColumn.cs
- CFGGrammar.cs
- ClientCultureInfo.cs
- WebPartEventArgs.cs
- TemplateBamlTreeBuilder.cs
- MarkupExtensionParser.cs
- AggregationMinMaxHelpers.cs
- XmlSchemaSimpleTypeList.cs
- OleDbConnectionPoolGroupProviderInfo.cs
- XmlLoader.cs
- DoubleLink.cs
- StateDesigner.TransitionInfo.cs
- DataRowView.cs